千家信息网

Linux内核编译与开发的示例分析

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,这篇文章将为大家详细讲解有关Linux内核编译与开发的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一.Linux内核简介linux kernel map:
千家信息网最后更新 2025年12月02日Linux内核编译与开发的示例分析

这篇文章将为大家详细讲解有关Linux内核编译与开发的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一.Linux内核简介

linux kernel map:

linux 系统体系结构:

linux kernel体系结构:

arm有7种工作模式,x86也实现了4个不同级别RING0-RING3,RING0级别***,

这样linux用户代码运行在RING3下,内核运行在RING0,这样系统本身就得到了

充分的保护

用户空间(用户模式)转到内核空间(系统模式)方法:

  • 系统调用

  • 硬件中断

linux kernel 体系结构:

虚拟文件系统VFS:

VFS(虚拟文件系统)隐藏各种文件系统的具体细节,为文件操作提供统一的接口

二.Linux内核源代码

linux内核下载www.kernel.org

目录结构:

解压linux kernel tar后目录

  • arch:根据cpu体系结构不同而分的代码

  • block:部分块设备驱动程序

  • crypto:加密,压缩,CRC校验算法

  • documentation:内核文档

  • drivers:设备驱动程序

  • fs(虚拟文件系统vfs):文件系统

  • include:内核所需的头文件,(与平台无关的头文件在include/linux中)

  • lib:库文件代码(与平台相关的)

  • mm:实现内存管理,与硬件体系结构无关的(与硬件体系结构相关的在arch中)

  • net:网络协议的代码

  • samples:一些内核编程的范例

  • scripts:配置内核的脚本

  • security:SElinux的模块

  • sound:音频设备的驱动程序

  • usr:cpio命令实现,用于制作根文件系统的命令(文件系统与内核放到一块的命令)

  • virt:内核虚拟机

linux DOC 编译生成:

linux源根目录/Documentation/00-INDEX:目录索引

linux源根目录/Documentation/HOWTO:指南

生成linux内核帮助文档:在linux源根目录(Documentation) 执行make htmldocs

ubuntu16下需要执行sudo apt-get install xmlto安装插件才可生成doc文档

后面开发中经常要改的是arch,drivers中的代码

三.Linux内核配置与编译

清理文件(在linux源码根目录):

  • make clean:只清理所有产生的文件

  • make mrproper:清理所有产生的文件与config配置文件

  • make distclean:清理所有产生的文件与config配置文件,并且编辑过的与补丁文件

配置(收集硬件信息如cpu型号,网卡等...):

  • make config:基于文本模式的交互配置

  • make menuconfig:基于文本模式的菜单模式(推荐使用)

  • make oldconfig:使用已有的.config,但会询问新增的配置项

  • make xconfig:图形化的配置(需要安装图形化系统)

配置方法:

1)使用make menuconfig操作方法:

1>按y:编译>连接>镜像文件

2>按m:编译

3>按n:什么都不做

4>按"空格键":y,n轮换

配置完并保存后会在linux源码根目录下生成一个.config文件

注意:在ubuntu11上要执行apt-get install libncurses5-dev来安装支持包

2)利用已有的配置文件模板(.config)

1>linux源码根目录/arch//configs/<具体某一的CPU文件>,把里面对应的文件copy并改名为.config至linux源码根目录下

2>利用当前运行已有的文件(要用ls /boot/ -a查看)把/boot/config-2.6.18-53.e15拷贝并改名为.config至linux源码根目录下执行以上操作就可以用make menuconfig在拷贝

.config文件上面修改文件了

编译内核:

1)make zImage

2)make bzImage

区别:在X86平台上,zimage只能用于小于512k的内核

获取详细编译信息:make zimage V=1 或 make bzimage V=1

编译好的内核在:arch//boot/目录下

注意:在把.config配置文件cp到根目录编译内核前,必须进入make menuconfig并保存退出(否则生不了效)

编译并安装模块:

1)编译内核模块:make modules

2)安装内核模块:make modules_install INSTALL_MOD_PATH=/lib/modules

更换本机器内核:将编译好的内核模块从内核源码目录copy至/lib/modules下

制作init ramdisk():输入执行命令mkinitrd initrd-2.6.39(任意) 2.6.39(可通过查询/lib/modules下的目录得到)

注意:

mkinitrd命令为redhat里面的,ubuntu的命令为:mkinitramfs -k /lib/modules/模块安装位置 -o initrd-2.6.39(任意) 2.6.39(可通过查询/lib/modules下的目录得到)

如果ubuntu里面没有mkinitramfs命令可以用apt-get install initrd-tools进行安装

安装内核模块:

1)手动

1>cp linux根目录/arch/x86/boot/bzImage /boot/mylinux-2.6.39

2>cp linux根目录/initrd-2.6.39 /boot/initrd-2.6.39

***修改/etc/grub.conf或/etc/lilo.conf文件

2)自动

1>make install:这个命令会自动完成上面的操作(查看当前内核版本:uname -r)

-----------------------------------------------------------------------------

四.linux内核模块开发

描述:

linux内核组件非常庞大,内核ximage并不包含某组件,而是在该组件需要被使用的时候,动态的添加到正在运行的内核中(也可以卸载),这种机制叫做"内核模块"的机制。内核模块通常通过使用makefile文件对模块进行编译

模块安装与卸载:

1)加载:insmod hello.ko

2)卸载:rmmod hello

3)查看:lsmod

4)加载(自动寻找模块依赖):modprobe hello

modprobe会根据文件/lib/modules/version/modules.dep来查看要加载的模块,看它是否还依赖于其他模块,如果是,会先找到这些模块,把它们先加载到内核

实例分析:

1)moduleDep/1(一个模块的编译)

 1 #include  2 #include  3  4 //模块入口函数 5 //__init:表示代码段中的子段,里面的内容只运行一次并且回收内存. 6 static int __init hello_init(void) 7 { 8     printk(KERN_EMERG "hello world!\n"); 9     return 0;10 }11 //模块卸载函数12 //__exit:13 static void __exit hello_exit(void)14 {15     printk(KERN_EMERG "hello exit!\n");16 }17 //内核符号导出 函数18 int add_integar(int a,int b)19 {20     return a+b;  21 }22 int sub_integar(int a,int b)23 {24     return a-b;  25 }26 27 module_init(hello_init);28 module_exit(hello_exit);29 //函数导出30 EXPORT_SYMBOL(add_integar);31 EXPORT_SYMBOL(sub_integar);

makefile:

#***次执行KERNELRELEASE是空的,所以执行else里面的 ifneq ($(KERNELRELEASE),)  obj-m :=hello.o  #else块  elseKDIR:= /lib/modules/2.6.18-53.el5/build  all: #KDIR    依赖内核模块源代码路径(内核编译安装路径) #PWD     表示内核代码在哪(当前目录) #modules 编译的是模块     make -C $(KDIR) M=$(PWD) modules   clean:     rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order  endif

2)moduleDep/2(两个模块的编译)

#include   #include   //模块可选信息  MODULE_LICENSE("GPL");//许可证声明  MODULE_AUTHOR("liyuan");//作者声明  MODULE_DESCRIPTION("This module is a param example.");//模块描述  MODULE_VERSION("V1.0");//模块别名  MODULE_ALIAS("a simple module");//模块别名   //模块参数 static char *name = "liyuan arg"; static int age = 30; //S_IRUGO是参数权限,也可以用数字 module_param(age,int,S_IRUGO); module_param(name,charp,S_IRUGO);   //使用外部文件函数 extern int add(int a,int b);   //声明 外部内核符号 函数 extern int add_integar(int a,int b); extern int sub_integar(int a,int b);  static int __init mains_init(void) {      //多文件编译      printk(KERN_EMERG"param hi");     int vle=add(1,2);     printk(KERN_EMERG"add value:%d\n",vle);     //模块参数       printk(KERN_EMERG" name : %s\n",name);      printk(KERN_EMERG" age : %d\n",age);      //使用其他模块的函数(内核符号导出)     int adds=add_integar(3,1);     int subs=sub_integar(3,1);     printk(KERN_EMERG" add_integar : %d\n",adds);     printk(KERN_EMERG" sub_integar : %d\n",subs);     return 0; }  static void __exit mains_exit(void) {     printk("param exit!"); }  module_init(mains_init);52 module_exit(mains_exit);

add.c

int add(int a,int b) {      return a+b; }

makefile

ifneq ($(KERNELRELEASE),) #两个以上内核源文件 生成单独的内核模块名ma  #内核ma obj-m :=ma.o #下面的ma-objs前面必须和上面一样为ma ma-objs := mains.o add.oelseKDIR:= /lib/modules/2.6.18-53.el5/build  all:         make -C $(KDIR) M=$(PWD) modules  clean:     rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order  endif

运行带参模块:insmod hello.ko name=yuan age=12

内核符号导出(/proc/kallsyms记录了内核中所有导出的符号的名字与地址):

一个内核模块的运行依赖另一个内核模块的函数实现,必须先运行***个内核模块,这样就需要进行内核符号导出。

注意:

错误信息:disagrees about version of symbol struct_module insmod:error inserting ...

开发内核模块时会出现,内核模块不匹配的情况.是你当前运行的linux内核与编译连接所依赖的

内核版本不匹配,解决方法:

  • 使用modprobe --force-modversion强行插入

  • 可使用uname -r进行查看当前运行的内核版本

printk内核打印:

中printk有8个优先级,按优先级递减的是:

  • KERN_EMERG 0

用于紧急的消息,常常是那些崩溃的消息

  • KERN_ALERT 1

需要立刻行动的消息

  • KERN_CRIT 2

严重情况

  • KERN_ERR 3

错误情况

  • KERN_WARNING(printk默认级别) 4

有问题的警告

  • KERN_NOTICE 5

正常情况,但是仍然值得注意

  • KERN_INFO 6

信息消息

  • KERN_DEBUG 7

用作调试消息

不管是哪个级别的都会在/var/log/messages里面打印出来(messages可以删除后,运行内核进行测试内核打印情况)控制台打印(优先级配置/proc/sys/kernel/printk)

6 4 1 7

  • Console_loglevel

  • Default_message_loglevel

  • Minimum_console_level

  • Default_console_loglevel

在vm+redhat安装2.6.39内核时出现的错误

启动时报could not find filesystem '/dev/root'

解决方法

a.通过make menuconfig选中以下对应的选项

General setup -->

[*] enable deprecated sysfs features to support old userspace tools

成功时下面那个也*了的

b.修改.config文件

修改.config文件中CONFIG_SYSFS_DEPRECATED_V2,将原本被注释掉的

CONFIG_SYSFS_DEPRECATED_V2 改成CONFIG_SYSFS_DEPRECATED_V2=y

关于"Linux内核编译与开发的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

内核 模块 文件 编译 配置 系统 根目录 运行 函数 命令 目录 代码 结构 体系 体系结构 模式 源码 符号 开发 信息 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 数据库为什么难做 广州智慧餐厅扫码点餐软件开发 广州为向互联网科技 长沙电子软件开发学校 深圳市互联港湾网络技术有限公司 福建计算机网络技术大专学校 软件开发oss是什么 手机生产测试软件开发 企业接入云服务器的好处 软件开发嵌入式培养 怀旧服任务奖励数据库 学习网络安全价格 学校 网络安全工作方面 mysql数据库字符编码更改 服务器端车牌识别助力智慧交通 itx服务器主板 医院网络安全管理体系的研究 java 数据库 数组 成都软件开发信息 总行与软件开发中心 信息安全技术应用软件开发 网络安全项目实践实训报告 场景设计数据库表 数据库包含哪两种设计特性 软件开发充值功能的实现 铁路开展网络安全宣传周活动 戴尔服务器调风扇权限 浦东新区威力网络技术售后服务 南通智能软件开发价格多少 浪潮服务器无法识别磁盘阵列
0