文章目录
1、Linux内核模块简介
Linux内核的整体架构本就非常庞大,其包含的组件也非常多,而我们怎样把需要的部分都包含在内核中呢?
如果把需要的所有功能都编译到Linux内核中。这会导致两个问题,一是生成的内核会很大,二是如果我们要在现有的内核中新增或删除功能,将不得不重新编译内核。
有没有另一种机制可使得编译出的内核本身并不需要包含所有功能,而这些功能需要被使用的时候,其对应的代码被动态地加载到内核中呢?
Linux提供了这样的机制,这种机制被称为模块(module)。模块具有这样的特点。
- 模块本身不被编译人内核映像,从而控制了内核的大小。
- 模块一旦被加载,它就和内核中的其他部分完全一样。
一个最简单的模块(module)
/*
* a simple kernel module: hello world
*
* Copyright (C) 2022 liefyuan (liefyuan@qq.com)
*
* Licensed under GPL v2 or later
*/
#include <linux/init.h>
#include <linux/module.h>
static int __init hello_init(void)
{
printk(KERN_INFO "Hello World enter\n");
return 0;
}
module_init(hello_init);
static void __exit hello_exit(void)
{
printk(KERN_INRO "Hello World exit\n");
}
module_exit(hello_exit);
MODULE_AUTHOR("Lief Yuan <liefyuan@qq.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("A simple Hello World Module");
MODULE_ALIAS("a simplest module");
这个最简单的内核模块只包含内核模块加载函数、卸载函数和对GPL v2 许可权限的声明以及一些描述信息。
2、Linux内核模块程序结构
一个Linux内核模块主要由如下几个部分组成:
- (1)模块加载函数
当通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的相关初始化工作。 - (2)模块卸载函数
当通过rmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块加载函数相关的功能。 - (3)模块许可证声明
许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染(Kernel Tainted)的警告。 - (4)模块参数(可选)
模块参数是模块被加载的时候可以传递给它的值,它本身对应模块内部的全局变量。 - (5)模块导出符号(可选)
内核模块可以导出的符号(symbol,对应于函数或变量),若导出,其他模块则可以使用本模块中的变量或函数。 - (6)模块作者等信息声明(可选)