邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛
分类: 嵌入式
2015-06-25 15:13:53
与版本依赖相关的头文件可查看 linux/version.h,这个头文件自动包含于linux/module.h,并定义了如下宏:
UTS_RELEASE
LINUX_VERSION_CODE
KERNEL_VERSION(major, minor, release)
和“内核依赖”类似,如果模块和某个给定内核工作,它也必须和内核一样了解目标处理器。
在装载模块时,内核会检查处理器相关的配置选项以便确保模块匹配于运行中的内核。如果模块在不同选项下编译,则不会装载该模块。
也就是说:比如在X86上编译的驱动程序,它在ARM平台上是无法运行的。
1. 头文件及许可证
大部分的内核代码中都要包含相当数量的头文件,以便获得函数、数据类型和变量的定义。2. 初始化函数
有几个头文件是专门用于模块的,必须出现在每个可装载的模块中。下面两个就是:
#include <linux/module.h> // 包含有可装载模块需要的大量符号和函数的定义
#include <linux/init.h > // 指定初始化和清除函数:module_init & module_exit
模块还应当指定代码所使用的许可证
MODULE_LICENSE("GPL");
3. 清除函数这里:
- static int __init initialization_function(void)
- {
- /* 这里是初始化代码 */
- }
- module_init(initialization_function);
__init标记对内核来讲是一种暗示:表示该函数仅在初始化期间使用。在模块被装载之后,模块装载器就会将初始化函数扔掉,这样就可以将该函数占用的内存释放出来,以作他用。
module_init的使用是强制性的,这个宏会在模块的目标代码中增加一个特殊的段,用于说明内核初始化函数所在的位置。没有这个定义,初始化函数永远不会被调用。
- static void __exit cleanup_function(void)
- {
- /* 这里是初始化代码 */
- }
- module_exit(cleanup_function);
清除函数没有返回值,因此声明为void。4. 初始化过程中的错误处理
__exit修饰词标记该代码仅用于模块卸载(编译器把该函数放在特殊的ELF段中)。
同样,module_exit声明对于帮助内核找到模块的清除函数是必需的。
时刻铭记:在内核中注册设备时,可能会失败。因此模块代码必须始终检查返回值,并确定所请求的操作是否真正成功。5. 模块装载竞争
具体介绍见书本。
参数可以在运行insmod命令装载模块时赋值。
insmod hellop howmany=10 whom=mom // 参考例子hellop.c
在insmod改变模块参数之前,模块必须让这些参数对insmod命令可见。参数必须使用module_param宏来声明。
module_param(变量的名称,类型,用于sysfs入口项的访问许可掩码),这个宏必须放在任何函数之外,通常是在源文件的头部。
module_param_array(param_array , int , ¶m_array_nr , S_IRUGO); // ¶m_array_nr是用于保存模块加载时输入数组参数的成员数目的。