Linux内核模块的编译

Linux内核采用了模块化的设计,允许内核在运行时插入或删除代码。这些代码组合在一起,形成了所谓的模块。

支持模块的好处是内核可以尽可能的小,可选的功能和驱动则利用模块来提供。

Hello, World!

/* hello world module */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

static int __init hello_init(void)  // 初始化函数,模块装载时被调用
{
        printk("<1> Hello, World!\n");
        return 0;
}

static void __exit hello_exit(void) // 退出函数,模块卸载的时候被调用
{
        printk(KERN_ALERT "hello module exit.\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("hello world");
MODULE_DESCRIPTION("first module");

模块的出口和入口都通过调用module_init()来注册到系统中,唯一的参数是模块的初始化函数。它其实是一个宏调用而非函数。 所有初始化函数必须满足如下形式:

类似的,退出函数使用module_exit()来注册,对应的函数作为出口函数,负责在返回(具体指了卸载内核模块)之前清理资源。 如果模块被静态地编译进内核,则这部分不会被调用,因为内核不需要卸载操作。

构建内核模块

内核模块的构建需要使用Makefile,使用一下模板可以完成编译:

另外在Clion中使用如下的CMakeLists.txt,可以消除错误的报错信息并拥有相应的代码提示。在运行时不需要指定可执行目标,直接运行编译即可在根目录编译产生main.ko(即为一个内核模块),使用insmod命令加载即可。

Last updated

Was this helpful?