第4章--Linux内核模块

一、内核模块简介

Linux提供了这样的机制,这种机制被称为模块(Module)。模块具有这样的特点。

  • 模块本身不被编译入内核映像,从而控制了内核的大小。
  • 模块一旦被加载,他就和内核中的其他部分完全一样。

二、内核模块程序结构

  1. 模块加载函数
    当通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的相关初始化工作。
  2. 模块卸载函数
    当通过rmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块加载函数相反的功能。
  3. 模块许可证声明
    许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将受到内核被污染的警告。
  4. 模块参数(可选)
    模块参数是模块被加载的时候可以传递给他的值,它本身对应模块内部的全局变量。
  5. 模块导出符号(可选)
    内核模块可以导出的符号(symbol,对应于函数或变量),若导出,其他模块则可以使用本模块中的变量或函数。
  6. 模块作者等信息声明(可选)

三、模块加载函数

模块加载函数以“module_init(函数名)”的形式被指定。它返回整型值,若初始化成功,应返回0。而在初始化失败时,应该返回错误编码。
在Linux中,所有标识为__init的函数如果直接编译进入内核,成为内核镜像的一部分,在连接的时候都会放在.init.text这个区段内。
所有的__init函数在区段.initcall.init中还保存了一份函数指针,在初始化时内核会通过这些函数指针调用这些__init函数,并在初始化成功后,释放init区段(包括.init.text、.initcall.init等)的内存。
除了函数以外,数据也可以被定义为__initdata,对于只是初始化阶段需要的数据,内核在初始化完后,也可以释放他们占用的内存。

四、模块卸载函数

模块卸载函数在模块卸载的时候执行,而不返回任何值,且必须以“module_exit(函数名)”的形式来指定。通常来说,模块卸载函数要完成与模块加载函数相反的功能。

五、模块参数

在装载内核模块时,用户可以向模块传递参数,形式为“insmod 模块名 参数名=参数值”,如果不传递,参数将使用模块内定义的缺省值。
如果模块被内置,就无法insmod了,但是bootloader可以通过在bootargs里设置“模块名.参数名=值”的形式给该内置的模块传递参数。
运行insmod或modprobe命令时,应使用逗号分隔输入的数组元素。

六、导出符号

模块可以使用如下宏导出符号到内核符号表中:
EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);
导出的符号可以被其它模块使用,只需使用前声明一下即可。EXPORT_SYMBOL_GPL()只适用于包含GPL许可权的模块。

七、模块声明和描述

在Linux内核模块中,我们可以用MODULE_AUTHOR、MODULE_DESCRIPTION、MODULE_BERSION、MODULE_DEVICE、MODULE_TABLE、MODULE_ALIAS分别声明模块的作者、描述、版本、设备表和别名。

你可能感兴趣的:(linux,驱动开发)