Linux 驱动模块的组成 gaunthan Posted on Jul 11 2016 ? Linux Driver ? ## 概述 一个驱动模块主要由以下部分组成: - 头文件(必选) - 模块参数(可选) - 模块功能函数(可选) - 其他(可选) - 模块加载函数(必须) - 模块卸载函数(必须) - 模块许可声明(必须) 一个规范的驱动模块应该包含上图所示的结构,这些结构在图中的顺序也是在源文件中的顺序。 ## 头文件 驱动模块会使用到内核中的许多函数,其中有两个头文件是必须包含的: ```c #include <linux/module.h> /* 包含了加载模块时需要使用的大量符号和函数定义 */ #include <linux/init.h> /* 包含了模块加载函数和模块卸载函数的宏定义 */ ``` ## 模块参数 模块参数是驱动模块加载时,传递给它的参数。如果一个模块需要实现两种类似的功能,可以通过传递一个参数到驱动模块,以决定其使用哪一种功能。 如前文图片所示,模块参数是可选的。 ### 模块参数的指定 参数需要在加载模块时指定,如`insmod module.ko param_1=value_1 param_2=value_2`。 ### 模块参数的定义 可以用`module_param(name, type, mode)`来为模块定义参数,例如下列代码定义了一个整型参数: ```c static int a = 1; module_param(a, int, S_IRUGO); ``` 参数的数据类型可以是: |可用数据类型|含义| |--|--| |byte|字节类型| |short|短整型| |ushort|无符号短整型| |int|整型| |uint|无符号整型| |long|长整型| |ulong|无符号长整型| |bool|布尔类型 |charp|字符指针| 由于内核不能完美地支持浮点数操作,因此模块参数的类型中没有浮点类型。 ## 模块加载函数 模块加载函数是模块加载时,由操作系统执行的函数。通过使用宏`module_init(your_init_func)`来指定。模块的初始化函数必须符合下面的形式: int my_init(void); 因为初始化函数通常不会被外部函数调用,所以不必导出该函数,可以将它标记为`static`。初始化函数会返回一个整型值,如果初始化顺利完成,那么它返回零;否则返回非零值。 ## 模块卸载函数 模块退出函数是模块卸载时,由操作系统执行的函数。通过使用宏`module_exit(your_exit_func)`来指定。模块的退出函数必须符合如下形式: void my_exit(void); 与初始化函数一样,可以将它标记为`static`。 ## 模块许可声明 模块许可声明表示模块受内核支持的程度。有许可权的模块会更受到开发人员的重视。如果一个模块没有包含任何许可权,那么就会认为是不符合规范的。这时,内核加载这种模块时,会收到内核加载了一个非标准模块的警告。开发人员不喜欢维护这种没有遵循许可权标准的内核模块。 使用宏`MODULE_LICENSE`指定模块的许可权,内核可以识别的许可权限有:  ## 其他 另外,`MODULE_AUTHOR()`宏和`MODULE_DESCRIPTION()`宏指定了代码作者和模块的简要描述,它们完全是用作信息记录目的的。 赏 Wechat Pay Alipay Linux 内核源码编译 Linux 驱动程序:实现Hello World模块