首先要理解Linux内核的加载过程。当计算机启动时,系统会将一部分内核代码加载到内存中。可以将内核代码分为两部分:在编译期间静态编译进内核的代码和编译为模块的代码。前者出现在内存中,称为内核镜像,对于后者,内核在运行时才会加载和卸载,这些代码则称为内核模块。下面,我们将详细阐释内核模块的加载过程。
内核模块的自动加载通常发生在如下情况下:
- 一个硬件设备在系统中被检测到,需要相应的驱动程序。
- 一个特定的命令被执行时(如,modprobe命令)。
接下来,我们来看看这个自动加载的过程及其中涉及到的步骤。
-
内核建立模块列表 - 内核会遍历系统上的目录/lib/modules/
/下的目录和所有子目录,来寻找可用的内核模块。在这个过程中,内核会读取每个模块的描述文件,来确定这个模块要执行的操作。一般来说,这些操作是驱动程序和系统支持库的形式。 -
模块的依赖关系 - 模块间的依赖关系非常重要,因为它可以帮助内核确保模块正确加载。内核会读取每个模块的描述文件,了解其依赖关系,确保按顺序加载依赖的模块。
-
加载模块 - 在确定好模块的依赖关系后,内核才回到模块所在目录,按顺序加载模块到内核镜像中。如果模块出现了任何问题,内核会发出相应的警告消息,并停止这个模块的运行。
举一个例子来说明,给出模块的代码。
#include<linux/module.h> //模块相关头文件
static int hello_init(void)//模块初始化
{
printk(KERN_ALERT "Hello World\n"); //利用 printk 写入日志系统内核日志
return 0;
}
static void hello_exit(void)//模块卸载
{
printk(KERN_ALERT "Goodbye cruel world\n");
}
module_init(hello_init);//入口宏,当初始化函数被调用
module_exit(hello_exit);//出口宏,当卸载函数被调用
MODULE_AUTHOR("OSChina Community");
MODULE_DESCRIPTION("Hello World Example");
MODULE_LICENSE("GPL");//许可证类型
上述示例中,使用了module_init
和module_exit
这两个函数将hello_init
和hello_exit
与内核模块关联起来。在初始化时,将调用hello_init
函数并在成功时返回0
,在卸载时,将调用hello_exit
函数。同时,建议在操作系统启动时查看系统日志来了解哪些模块已自动加载。
总结一下,Linux内核的内核模块加载过程通常分为三个部分:建立模块列表、识别模块之间的依赖关系和加载模块。内核模块一般在硬件检测到后自动加载,也可以使用modprobe
手动加载。要编写自己的内核模块,需要了解在模块代码中使用的宏和函数。除此之外,模块描述文件也是实现模块的重要部分,需要指定模块的依赖关系和其他系统参数。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Linux内核(内核模块)的加载过程 - Python技术站