内核模块开始学习前,一定是最先接触到内核模块三要素(面试),驱动入口、驱动出口和协议的遵循。
1.内核模块三要素(面试)
//修饰模块化驱动的入口函数
module_init(demo_init);
//修饰模块化驱动的出口函数
module_eixt(demo_exit);
//遵循GPL开源协议
MODULE_LICENSE("GPL");
记住就像没有那么多为什么
这个三要素没有那么多为什么,记住就可以了,每一个驱动模块都要遵循。
这里会涉及到三个宏,module_init、module_exit、MODULE_LICENSE。我们到内核里面去找一下他们的原型,
module_init 是 linux kernel 绝大多数模块的起始点,我们所熟悉的应用程序都是从一个 main() 函数开始运行的,但内核模块都是从module_init开始的,向系统申请资源。
有开始就有结束,与 module_init 对应的就是 module_exit 。module_exit 负责进行一些和init反向的活动,例如:
- init 是注册驱动,exit 就是注销驱动
- init 是申请资源,exit 就是释放资源
- init 是创建节点,exit 就是销毁节点
注意exit中活动的顺序,应该对应 init 中活动的逆序
MODULE_LICENSE是固定的,意思是要遵循什么开源协议,使用是GPL
下面的是小例子
//头文件
#include <linux/init.h>
#include <linux/module.h>
1.1.1:入口函数函数(向系统申请资源)
static int __init demo_init(void)
{
//__init 用于修饰dome_init函数,作用是把这个函数放到init代码中
//__init被定义在init.h中 #define __ init __sertion(.init.text)
printk("exit demo_init")
}
1.1.2:出口函数(释放向内核申请的资源
static void __exit demo_exit(void)
{
printk("exit demo_exit")
}
1.1.3:许可证(遵循GPL开源协议)
//修饰模块化驱动的入口函数
module_init(demo_init);
//修饰模块化驱动的出口函数
module_eixt(demo_exit);
//遵循GPL开源协议
MODULE_LICENSE("GPL");
记住就像没有那么多为什么
上图以demo函数做一个例子,其中的 static 和 __init 不是必须的:
- static 是为了函数不被模块外部错误引用(注意不可使用内联定义)
- __init 是告诉系统这个是用来初始化的函数,运行后不必再保留在内存中
- 入口格式:int (*) (void)
- 出口格式:void (* ) (void)