Chinaunix首页 | 论坛 | 博客
  • 博客访问: 829062
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: 嵌入式

2015-06-25 15:13:53

接上一篇。
本来想写在一起的,结果发现原来的博客居然不能编辑了。
只好另开一篇了。感觉有点记流水账啊,但是觉得这书写的真心好,每句话都觉得该记下来。

内核依赖

与版本依赖相关的头文件可查看 linux/version.h,这个头文件自动包含于linux/module.h,并定义了如下宏:
UTS_RELEASE          
LINUX_VERSION_CODE
KERNEL_VERSION(major, minor, release)

平台依赖

和“内核依赖”类似,如果模块和某个给定内核工作,它也必须和内核一样了解目标处理器。
在装载模块时,内核会检查处理器相关的配置选项以便确保模块匹配于运行中的内核。如果模块在不同选项下编译,则不会装载该模块。
也就是说:比如在X86上编译的驱动程序,它在ARM平台上是无法运行的。

内核符号表

insmod使用公共内核符号表来解析模块中未定义的符号,公共内核符号表中包含了所有的全局内核项(即函数和变量)的地址,这是实现模块化驱动程序所必须的。

Linux内核头文件提供了一个方便的方法来管理符号对模块外部的可见性,从而减少了可能造成的名字空间污染。
如果一个模块需要向其他模块导出符号,则应该使用下面的宏。
EXPORT_SYMBOL(name)
EXPORT_SYMBOL_GPL(name)



模块的组成

1. 头文件及许可证

大部分的内核代码中都要包含相当数量的头文件,以便获得函数、数据类型和变量的定义。
有几个头文件是专门用于模块的,必须出现在每个可装载的模块中。下面两个就是:
#include <linux/module.h>     // 包含有可装载模块需要的大量符号和函数的定义
#include <linux/init.h >      // 指定初始化和清除函数module_init & module_exit

模块还应当指定代码所使用的许可证
MODULE_LICENSE("GPL");
2. 初始化函数
  1. static int __init initialization_function(void)
  2. {
  3.     /* 这里是初始化代码 */
  4. }
  5. module_init(initialization_function);
这里:
    __init标记对内核来讲是一种暗示:表示该函数仅在初始化期间使用。在模块被装载之后,模块装载器就会将初始化函数扔掉,这样就可以将该函数占用的内存释放出来,以作他用。
    module_init的使用是强制性的,这个宏会在模块的目标代码中增加一个特殊的段,用于说明内核初始化函数所在的位置。没有这个定义,初始化函数永远不会被调用。
3. 清除函数

  1. static void __exit cleanup_function(void)
  2.     {
  3.         /* 这里是初始化代码 */
  4.     }
  5.     module_exit(cleanup_function);
清除函数没有返回值,因此声明为void。
__exit修饰词标记该代码仅用于模块卸载(编译器把该函数放在特殊的ELF段中)。
同样,module_exit声明对于帮助内核找到模块的清除函数是必需的。
4. 初始化过程中的错误处理
时刻铭记:在内核中注册设备时,可能会失败。因此模块代码必须始终检查返回值,并确定所请求的操作是否真正成功。
具体介绍见书本。

5. 模块装载竞争


模块参数

参数可以在运行insmod命令装载模块时赋值。
insmod hellop howmany=10 whom=mom   // 参考例子hellop.c

在insmod改变模块参数之前,模块必须让这些参数对insmod命令可见。参数必须使用module_param宏来声明。
module_param(变量的名称,类型,用于sysfs入口项的访问许可掩码,这个宏必须放在任何函数之外,通常是在源文件的头部。


module_param_array(param_array , int , &param_array_nr , S_IRUGO);   // &param_array_nr是用于保存模块加载时输入数组参数的成员数目的。



第二章终于完结了,感觉是流水账,但是工欲善其事,必先利其器。概念搞懂了,就不难了。


阅读(913) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~