Linux 内核模块程序结构:
(1)模块加载函数
(2)模块卸载函数
(3)模块许可证声明
(4)模块参数
(5)模块导出符号
(6)模块作者等信息声明
模块加载函数
一般以 __init 标识
在 Linux 中,所有标识为 __init 的函数如果直接编译进内核,成为内核镜像的一部分,在连接的时候都会放在 .init.text 这个区段内。
所有的 __init 函数在区段 .initcall.init中还保存了一份函数指针,在初始化时内核会通过这些函数指针调用这些 __init 函数,并在初始化完成后,释放 init 段(包括.init.text、.initcall.init等)的内存。
模块卸载函数
模块卸载函数一般以__exit标识声明。
模块参数
以"module_param(参数名,参数类型,参数读/写权限)"为模块定义一个参数。
导出符号
linux的“/proc/kallsyms”文件对应着内核符号表,它记录了符号以及符号所在的内存地址。
模块可以使用如下宏导出符号到内核符号表中:
EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);
导出的符号可以被其他模块使用,只需使用前声明一下即可。
模块的声明与描述
MODULE_AUTHOR:模块的作者
MODULE_DESCRIPTION:模块的描述
MODULE_VERSION:模块的版本
MODULE_DEVICE_TABLE:模块所支持的设备表
MODULE_ALIAS:模块的别名
模块的使用计数
linux2.6以后的内核为不同类型的设备定义了struct module *owner域,用来指向管理此设备的模块。
当开始使用摸个设备时,内核使用try_module_get(dev->owner)去增加管理此设备的owner模块的使用计数;当不再使用此设备时,内核使用module_put(dev->owner)减少对管理此设备的管理模块的使用计数
模块编译
模块的编译很简单,自己百度就可以了,这里只说明一点:
添加EXERA_CFLAGS = -g -O0,可以得到包含调试信息的hello.ko 模块。
模块总结
加载模块:insmod或modprobe -> 该命令执行后,会在/sys/module/目录下生成一个模块的目录,在里面可以查看到模块的相关信息。
卸载模块:rmmod
查看模块:lsmod -> 该命令实际上是读取并分析“/proc/modules”文件,可以使用cat命令查看该文件
获得模块的信息:modinfo