内核模块可以简单理解为运行在内核空间的程序。与用户空间的应用程序一样其也有固定的模式。
第一个内核模块 先来看一个标准的应用程序- HelloWorld.c
#include "stdio.h"
int main(int argc, char** argv)
{
printf("Hello World!");
}
以上代码大家一定不会陌生。还记得第一次学习这个程序时的心情么,大多数人可能都不理解它为什么要这么写,只是记住了它的格式而已。那么对于内核模块也是一样的,最开始我们不需要理解那么多,只需要记住内核模块的格式即可。
第一个内核模块- HelloKernelModule.c
#include "linux/init.h"
#include "linux/module.h"
static int __init hello_module_init(void)
{
printk("Initialize modulen");
return 0;
}
static void __exit hello_module_exit(void)
{
printk("Exit modulen");
}
module_init(hello_module_init);
module_exit(hello_module_exit);
MODULE_LICENSE("GPL");
module_init() 和 module_exit()
module_init()用于声明模块的入口函数。用户应用程序的入口函数名固定为main这是c语言标准规定的。而内核模块的入口函数名可以根据需要随便起名。只需要用module_init()声明一下即可。
module_exit()用于声明内核模块退出(卸载)时需要执行的函数。
如果你了解C++,那么可以把module_init()和module_exit()声明的函数看作是C++类的构造函数和析构函数。当模块被加载时会执行module_init()声明的函数(代码中的hello_module_init()),当模块被卸载时会执行module_exit()声明的函数(代码中的hello_module_exit())。
printkC语言的标准函数是建立在操作系统外层API之上的,而内核模块属于操作系统的内层因此不能直接调用C语言标准函数,如printf()便无法使用 。在内核打印信息需要使用printk()。该函数的用法可以在网上找到很多说明,这里就不赘述了。
MODULE_LICENSEMODULE_LICENSE用于声明当前模块执行的开源协议标准。由于kernel是开源项目,如果你编写的内核模块不兼容GPL协议,内核会认为你编写的模块‘污染’了内核。 因此一般情况都需要用MODULE_LICENSE对模块的协议进行声明。
在内核代码include/linux/module.h中可以看到MODULE_LICENSE,及其可以使用的协议。
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)



