LINUX内核设计与实现模块

LINUX内核模块的意义:

允许内核在运行时动态地向其中插入或从中删除代码.

 

16.1 构建模块

我们经常做的事情就是往内核源码树添加我们自己的驱动源码,便交付内核去编译.下面以一个例子来说明此流程.

比如说,我们有个驱动,涉及到两个源码文件:fishing-main.cfishing-line.c.而且要独立于一个文件夹下.假设我们的驱动是字符设备.那么,我们可以在/deivers/char/目录下建立一个名为fishing的子目录.因此,我们的源码位于/deivers/char/fishing/目录下.我们必须告诉内核到我们指定的目录下去编译我们的源码,通过以下方式告诉内核进入指定的目录:

方式一:必须编译

修改drivers/char/Makefile文件中加入:

Obj-m +=fishing/

这行代码的意思就是告诉模块构建系统编译模块时需要进入fishing/子目录中.

方式二:选择性编译

我们的驱动模块是否参与编译可以通过特殊配置选项来裁决.这也是我们常用的手段.比如可能的CONFIG_FISHING_POLE(通过修改drivers/char/Kconfig文件).如下:

Obj-$(CONFIG_FISHING_POLE) += fishing/

好了,内核进入了我们指定的目标目录,下面就要求内核把我们的目标源码文件参与编译.当然,首先需要添加一个新的Makefile文件.编译方式也有两种:

方式一:必须编译

Obj-m += fishing.o

方式二:选择性编译

Obj-$(CONFIG_FISHING_POLE) += fishing.o

当然,出现两个或以上的文件时,Makefile需要作如下修改:

Obj-$(CONFIG_FISHING_POLE) += fishing.o

Fishing-objs := fishing-main.o fishing-line.o

这样fishing-main.cfishing-line.c就一起编译和连接到fishing.ko模块内.

最后,如果在构建文件时需要额外的编译标记,只需要在Makefile中添加如下指令:

EXTRA_CFLAGS += -DTITANIUM_POLE

 

16.1.2 放在内核代码外

在目标源码树目录下建立一个Makefile文件,内容如下:

Obj-m := fishing.o

这样就可以把fishing.c编译成fishing.ko.

如果存在多个源文件,Makefile内容如下:

Obj-m := fishing.o

Fishing-objs := fishing-main.o fishing-line.o

这样一来,fishing-main.cfishing-line.c就一起被编译和连接fishing.ko模块内.

16.2 安装模块

当我们编译好内核,需要编译我们自己的模块源码时.执行如下源码:

Make modules_install

 

16.3 产生模块依赖性

LINUX模块之间存在依赖性.内核依赖关系的信息,可以通过下面的命令查看:

Depmod

如果只为新模块生成依赖信息,而不是生成所有的依赖关系,通过下面命令查看:

Depmod –A

模块的依赖关系信息存放在/lib/modules/version/modules.dep文件中

 

16.4 载入模块

最简单的命令:insmod

加载驱动:

Insmod module

卸装驱动:

Rmmod module

比较先进的工具:modprobe.它提供了模块依赖性分析,错误的智能检查报告及其他功能和选项.如果当前装载有依赖其他模块,将自动装载其所依赖的模块.强烈建议使用此工具:

装载:

Modprobe module [module parameters]

Module指定了需要载入的模块名称,后面的参数将在模块加载时传入内核.

卸载:

Modprobe –r modules

卸载过程中会自动卸载其依赖的模块.

 

16.5 管理配置选项

导入自定义Kconfig文件:

本节主要围绕Kconfig文件展开.Kconfig文件是内核组织编译的一种手段,其中对Makefile有效的内容意义相当于变量--不同的变量值(有三个,m,y,n)去控制Makefile文件的编译动作,是编译进内核还是模块还是索性就不编译.比如我们在drivers/char/fishing目录下建立了一个Kconfig文件,需要在企图上一级Kconfig引入此Kconfig文件.例如我们可以在drivers/char目录下的Kconfig文件添加下面一行指令:

Source "drivers/char/fishing/Kconfig"

Kconfig文件中加入一个配置选型:

Config FISHING_POLE

Tristate "Fish Master XL support"

Default n

Help

If you say Y here,support for the Fish Master XL 2000....

 

If unsure,say N.

驱动的帮助信息

配置选项第一行定义了该选项代表的配置目标.注意CONFIG_前缀产需要写上.

第二行声明选项类型为tristate,也就是说可以被编译进内核(Y),也可作为模块编译(M).或者不编译它(N).

第三行是选项的默认选择,这里默认操作是不编译它.

Kconfig文件的意思请参考其他相关资料.

 

16.6 模块参数

模块参数对于驱动程序而言属于全局变量,也将出现在sysfs文件系统中.定义一个模块参数通过module_param()完成.

Module_param(name,type,perm);

各参数的意义如下:

Name:参数名;

Type:name的类型,char,int;

Perm:sysfs文件系统下对应文件的权限,该值是八进制的格式,比如0644(所有者可读写,组内可读,其他人可读).此值为0表示禁止所有sysfs.

使用模块变量的示意代码如下:

Static int allow_live_bait = 1;

Module_param(allow_live_bait,bool,0644);

如果模块的外部参数名称不同于它对应的内部变量名称,这时就该用宏module_param_name()定义.示意代码如下:

Module_param_named(name,variable,type,perm);

Name是外部可见参数名称,参数variable是对数对应的内部全局变量名称.:

Static unsigned int max_test = DEFAULT_MAX_LINE_TEST;

Module_param_named(maximum_line_test,max_test,int,0);

更常见的是,需要一个charp类型定义模块参数(一个字符串),内核将用户提供的这个字符串拷贝到内存,将你的变量指向该字符串.:

Static char *name;

Module_param(name,charp,0);

更多的模块参数见LDD3.

 

16.7 导出符号表

主要完成模块间通讯的一种接口.通过EXPORT_SYMBOL()指令导出.实际使用的示意代码如下:

Int get_pirate_beard_color(void)

{

Return pirate->beard->color;

}

EXPORT_SYMBOL(get_pirate_beard_color);

这样,get_pirate_beard_color函数也可以被其他模块调用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值