Linux module

1. module

1.1 模块加载函数 __init

· 模块加载函数,当通过 insmod 或 modprobe 命令加载kernel module时,module的初始化函数会被自动调用执行,完成模块的初始化
· insmod 命令是单独加载内核模块而已,modprobe 命令加载模块的同时,还加载模块依赖的其他模块
· rmmod 命令用来卸载内核模块,而 modprobe -r 命令用来卸载指定的内核,并且卸载该模块依赖的所有模块

1.1.1 代码段

#include <liunx/init.h>
static __init int hello_init(void)
{
	/* module init code */
	return 0;
}
module_init(hello_init);

· #include <liunx/init.h> 是Linux初始化相关的头文件
· static 为静态函数,只具备文件作用域
· __init 标识,有__init标识的函数只会在kernel初始化的时候才被加载到内存调用,调用结束后对应的代码段内存空间被释放,再次调用该标识的函数就会报错
· module_init 是一个回调函数

1.1.2 数据段

static __initdata int a = 1;

· __initdata标识,拥有该标识的数据,在kernel初始化完成后,该数据在内存占用的数据段会被释放

1.2 模块卸载函数 __exit

1.2.1 代码段

#include <liunx/init.h>	
static __exit void hello_exit(void)
{
	/* module exit code */
	return 0;
}
module_exit(hello_exit);

· #include <liunx/init.h> 是Linux初始化相关的头文件
· static 为静态函数,只具备文件作用域
· __exit 标识,有__exit标识的函数只会在模块卸载时才被到加载到内存中,调用结束后对应的代码段内存空间被释放,再次调用该标识的函数就会报错。但如果模块是编译到kernel中,那模块将失去热插拔的特性,卸载模块函数也失去意义
· module_init 是一个回调函数

1.2.2 数据段

static __exitdata int a = 1;

· __exitdata标识,拥有该标识的数据,在kernel模块卸载完成后,该数据在内存占用的数据段会被释放

1.3 模块许可证声明

· 许可证说明:描述kernel module的许可权限,如果不声明LICENSE(许可证),module加载时,将会收到kernel被污染(Kernel Tainted)的警告
· 在Linux module领域,可接受的LICENSE包括:''GPL''、''GPL v2''、''GPL and additional rights''、''Dual BSD/GPL''、''Dual MPL/GPL''、''Proprietary''(关于module是否可采用非GPL许可权,如''Proprietary''现在还是饱受争议的)
· 大多数情况下,kernel module都应遵循GPL兼容许可权,最常见的是使用GPL v2版本的

1.3.1声明许可证的实现

以最常见的GPL v2为例

#include <linu/module.h>

MOUDLE_LICENSE("GPL v2");

1.3.2 使用module"规避"GPL

· 只使用GPL module的运行结果,间接的使用module''规避''GPL,但这也是具有争议的
· 一般认为,保守的做法是Linux kernel 不能使用非GPL LICENSE

1.4 模块参数(可选)

1.5 模块导出符号(可选)

· /proc/kallsyms 文件对应着内核符号表,里面记录着符号以及符号所在的内存地址
module 通过下面的宏将符号导出到内核符号表中

#include <linux/export.h>

EXPORT_SYMBOL(符号名);			//非GPL许可证的module使用
EXPORT_SYMBOY_GPL(符号名);		//	只适用与GPL许可证的module使用

1.6 模块作者等信息(可选)

#include <linux/module.h>

MODULE_AUTHOR(author);				//作者信息
MODULE_DESCRIPTION(description);	//描述模块信息
MODULE_VERSION(version_string);		//版本描述
MODULE_DEVICE_TABLE(table_info);	//对于USB,PCI等设备驱动,通常会创建一个表明该驱动模块所支持的是设备
MODULE_ALIAS(alternate_name);		//模块别名

1.7 模块使用计数(附加)

· kernel module的使用计数为0时,才允许module的卸载
· module的使用计数的增加和减少由kernel操作,操作对象为dev -> owner
· 但可能特殊情况我们也需自己管理module的使用次数

#include <linux/module>

try_module_get(dev -> owner);	//module 使用次数加一
module_put(dev -> owner);		//module 使用次数减一

1.8 模块的依赖性

1.8.1 模块的命名与别名

· 模块的名字一般是系统规定的,为你模块文件去掉后缀后的名字,比如DS18B20.ko的模块,模块名字一般为DS18B20

1.8.1.1 模块名字的宏
#include <linux/module.h>

.owner = THIS_MODULE;	//THIS_MODULE为当前模块名的宏
1.8.1.2 模块的别名
#include <linux/module.h>

MODULE_ALIAS("my_driver_name"); //为当前模块创建一个别名
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值