linux设备驱动(二)

我的未来我决定 提交于 2020-01-08 20:42:12

内核模块结构

加载函数

通过insmod或者modprobe加载模块时,加载函数将会自动执行

卸载函数

通过rmmod卸载模块时,卸载函数将会被自动执行

许可证声明

描述内核模块的许可权限,如果不声明,加载时将收到内核被污染(Kernel Tainted)的警告
大多数情况下,采用GPL v2

MODULE_LICENSE("GPL v2");

模块参数

模块参数是模块被加载时,可以传递给它的值,对应于模块内部的局部变量

模块导出符号

模块可以导出符号(symbol),对应函数或变量,如果导出,则其它模块就可以使用了

加载函数

形式被固定为 module_init(函数名);,返回整型值,若初始化成功,则返回0,失败返回错误码

在内核中,也可以通过request_module(模块名)函数灵活地加载其它内核模块

一般以__init标识对初始化函数做额外声明,原型如下

#define __init __attribute__ ((__section__ (".init.text"))) __cold

指定该函数,在链接的时候,放到init.text段,初始化的时候,调用这些函数,初始化完成后,释放内存

数据也可以用__initdata进行标识,链接时,放到init.data区段,同样在初始化完成后,释放其内存

static int __init hello_init(void){...}
static int a __initdata=1;

卸载函数

形式被固定为module_exit(函数名),不返回任何值,卸载函数利用__exit进行修饰
同样,只是在卸载阶段起作用的变量,也可以利用__exitdata进行修饰

模块参数

用户态通过main函数即可完成参数传递,在内核态中,可以使用module_param(参数名,参数类型,参数权限)为模块定义参数,例如:

static int a=10;
module_param(a, int, 0644);

调用形式为

insmod 模块名 参数名=参数值
insmod book.ko book_name=‘nihao’ book_num=100

也可以设置参数数组,形式为module_param_array(数组名,数组类型,数组长度,参数权限)

如果调用的时候,参数缺省,则使用内部缺省值

如果是内置模块,则无法通过insmod加载模块,但是可以通过bootloader,在bootargs中设置模块名.参数名=值的形式,给内置模块传递参数

参数加载后,在/sys/module/模块名/的目录下,将出现parameters目录,里面可以查看参数信息

参数类型

  • byte
  • short
  • ushort
  • int
  • uint
  • long
  • ulong
  • charp:字符指针
  • bool
  • invbool:布尔的反

权限类型

相关宏定义在src/include/stat.h

S_IRUGO=(S_IRUSR|S_IRGRP|S_IROTH)
S_IRUSR:用户读  00400
S_IRGRP:用户组读 00040
S_IROTH: 其他读 00004

因此,权限可以用宏或者八进制表示法

导出符号

符号包括函数和变量,/proc/kallsyms文件对应内核符号表,记录了符号以及符号所在的内存地址

模块可以使用以下两种方法导出符号到内核符号表,导出的符号可以被其它模块使用,但是使用前需要声明

EXPORT_SYMBOL(符号名);         //所有模块都能使用
EXPORT_SYMBOL_GPL(符号名);  //GPL许可的模块能使用

模块的声明与描述

作者

MODULE_AUTHOR(作者名字);

描述

MODULE_DESCRIPTION(“描述内容”);

版本

MODULE_VERSION(“版本号”);

设备表

对于USB、PCI等设备驱动,通常会创建设备表,表明支持的设备

MODULE_DEVICE_TABLE(type, name);

别名

MODULE_ALIAS(“别名”);

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!