编写一个简单的Linux可加载内核模块

什么是Linux可加载内核模块?Linux可加载内核模块(Loadable Kernel Module,LKM)是Linux内核向外部提供的一个接口。我们知道Linux内核是一个单内核,它集成了很多的内容。那么当我想向Linux内核中写入点新功能怎么办?需要向Linux内核添加一个新的设备驱动怎么办?修改内核源码,然后重新编译?那不得麻烦死。所以Linux就提供了模块加载机制。那样,我们就可以编写自己的可加载内核模块,然后加载到Linux内核,成为内核的一部分。当我们不需要它的时候,可以把它卸载。这样添加新的设备驱动也变得十分容易了。 模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。

编写模块源码

hello.c

#include <linux/module.h>    // included for all kernel modules
#include <linux/kernel.h>    // included for KERN_INFO
#include <linux/init.h>        // included for __init and __exit macros

static int __init hello_init(void)      //模块入口函数
{
    printk(KERN_INFO "Hello world!\n");
    return 0;    // Non-zero return means that the module couldn't be loaded.
}

static void __exit hello_exit(void)       //模块出口函数,无返回值
{
    printk(KERN_INFO "Cleaning up module.\n");
}

module_init(hello_init);
module_exit(hello_exit);

内核模块的编写规范自行Google

编写Makefile

obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
 
all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules
 
clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

Makefile的编写规范自行Google

编译并测试

编译:在工作目录下执行

make

加载模块到内核:

sudo insmod hello.ko

运行:

sudo dmesg

使用lsmod查看已经加载的模块:

lsmod | grep hello

卸载模块:

sudo rmmod hello
sudo dmesg

comments powered by Disqus