《Linux4.0设备驱动开发详解》笔记--第四章:Linux内核模块
2016-05-18 11:03
435 查看
4.1 内核模块程序结构
加载:insmod,modprobe(同时加载模块的依赖模块)卸载:rmmod
查看已加载的模块及模块间的依赖关系:lsmod,实际上是分析/proc/modules文件
已加载的模块信息放在/sys/module目录下,没加载一个模块就会在该目录下生成一个以模块名命名的目录,“tree -a”可获取目录树
模块许可声明:申明许可权限,否则将收到内核被污染警告,一般申明为MODULE_LICENSE(“GPL v2”)语句申明采用GPL v2.
模块参数(可选):模块被加载的时候可以传递给它的值,它本身对对应模块的内部的全局变量
模块导出符(可选):其他模块可以使用模块导出的函数和变量
模块作者等信息声明
4.2 模块加载函数
Linux内核模块加载函数一般以__init标识申明,如static int __init initialization_function(void) { /*初始化代码*/ } module_init(initialization_function);
初始化成功返回0,否则返回错误码。
request_module(const char* fmt, …):灵活加载内核模块
数据也可以定义为__initdata,只是在初始化的阶段需要的数据,结束后释放占用的内存
4.4 模块卸载函数
一般以__exit标识申明,如static void __exit cleanup_function(void) { /*释放代码*/ } module_exit(cleanup_function);
被直接编译进内核的模块的卸载函数会被省略,不编译进内核,因为模块被内置了,也就不会被卸载。
4.5 模块参数
module_param(参数名,参数类型,参数读写权限):为模块定义一个参数,如下定义一个int参数和char指针参数static char *book_name = "dissecting Linux Deice Driver"; module_param(book_name, char, S_IRUGO); static int book_num = 4000; module_param(book_num, int, S_IRUGO);
“insmod (或modprobe) 模块名 参数名 = 参数值”,不传递则用缺省值,模块被内置时用bootloader通过bootargs里设置“模块名.参数 = 值”给内置模块传递参数。
参数数组:module_param_array(数组名,数组类别,数组长度,参数读写权限)
/sys/module下有已加载模块命名的目录,当“参数读写权限”为0,则此参数不存在sysfs文件系统下对应的节点,否则此模块的目录下会出现parameter目录,其中包含以参数名命令的文件节点,文件权限与设定的权限一致。
允许insmod和modprobe命令时,用逗号隔开输入的数组元素
例:定义两个参数的模块
/*====================================================================== A kernel module: book This example is to introduce module params The initial developer of the original code is Baohua Song <author@linuxdriver.cn>. All Rights Reserved. ======================================================================*/ #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static char *book_name = "dissecting Linux Device Driver"; static int num = 4000; static int book_init(void) { printk(KERN_INFO " book name:%s\n",book_name); printk(KERN_INFO " book num:%d\n",num); return 0; } static void book_exit(void) { printk(KERN_INFO " Book module exit\n "); } module_init(book_init); module_exit(book_exit); module_param(num, int, S_IRUGO); module_param(book_name, charp, S_IRUGO); MODULE_AUTHOR("Song Baohua, author@linuxdriver.cn"); MODULE_DESCRIPTION("A simple Module for testing module params"); MODULE_VERSION("V1.0");
通过insmod加参数和不加参数实验,在/var/log/messages文件中查看内核的输出
在/sys/module/book/parameters目录下输入tree查看参数文件节点
4.6 导出符号
/proc/kallsyms文件记录了符号及符号所在的内存地址导出符号:EXPORT_SYSBOL(符号名),EXPORT_SYSBOL_GPL(符号名)(只适用于包含GPL许可权的模块)
例:
/*====================================================================== A simple kernel module to introduce export symbol The initial developer of the original code is Baohua Song <author@linuxdriver.cn>. All Rights Reserved. ======================================================================*/ #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); int add_integar(int a,int b) { return a+b; } int sub_integar(int a,int b) { return a-b; } EXPORT_SYMBOL(add_integar); EXPORT_SYMBOL(sub_integar);
4.7 模块申明与描述
MODULE_AUTHOR(author);MODULE_DESCRIPTION(description);
MODULE_VERSION(version_string);
MODULE_DEVICE_TABLE(table_info);
MODULE_ALIAS(alternate_name);
对于
4000
USB, PCI等设备驱动,通常创建一个MODULE_DEVICE_TABLE来表明驱动模块支持的设备
4.8 模块的使用计数
try_module_get(&module)和module_put(&module):模块计数管理接口try_module_get(&module):增加模块使用计数,返回0,调用失败,希望使用的的模块不存在或正在被卸载
module_put(&module):减少模块使用计数
模块的使用计数一般不由模块本身管理,由内核更底层的代码(总线驱动或者此类设备共用的核心模块)来实现,以简化驱动开发
当设备正在使用的时候,模块不可以被卸载
4.9 模块编译
Makefile模块包含多个.c文件,则Makefile写法
obj-m := modulename.o modulename-objs := file1.o file2.o ...
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- 神器SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程