前言:本文主要介绍了LKM的基本概念和如果配置编译环境,编译加载一个简单的LKM。适合linux初学者。
什么是可加载内核模块
可加载内核模块(Loadable Kernel Module,LKM允许在不重编译内核和重启系统的条件下对类Unix系统的系统内核进行修改和扩展.大多数的Unix派生系统,包括Linux,BSD,OSX等都支持这个特性.
本文着重描述编译执行一个”hello world”LKM的过程.相关的代码可以在这里下载.下面的命令和代码都在Ubuntu 11.10和12.10上测试通过了.在其他的Linux发行版上也许需要做一些细微的修改.
编写LKM的基本流程
1, 安装module-assistant包
2, 创建主文件hello.c和Makefile
3, 编译hello.c
4, 将编译好的模块插入到当前内核中
5, 测试完成后移除相关的内核模块
Debian和Ubuntu都提供了moddule-assistant的包,包括了编写LKM需要的所有包.可以通过一下方式安装:
sudo -i apt-get install module-assistant m-a prepare
module-assistant做的事情并没有多么高端.它仅仅是一个安装内核源码包的工具.下面的命令也可以安装我们编译需要的l依赖包:
sudo apt-get install build-essential linux-headers-$(uname -r)
这是一个hello world的源码…在本文提供的压缩包里有.作用是加载内核模块和卸载内核模块的时候输出一个hello world
// Defining __KERNEL__ and MODULE allows us to access kernel-level code not usually available to userspace programs. #undef __KERNEL__ #define __KERNEL__ #undef MODULE #define MODULE // Linux Kernel/LKM headers: module.h is needed by all modules and kernel.h is needed for KERN_INFO. #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_cleanup(void) { printk(KERN_INFO "Cleaning up module.\n"); } module_init(hello_init); module_exit(hello_cleanup);
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
到工作目录下执行make就可以了
$ make make -C /lib/modules/3.0.0-17-generic/build M=/var/www/lkm modules make[1]: Entering directory `/usr/src/linux-headers-3.0.0-17-generic' CC [M] /var/www/lkm/hello.o Building modules, stage 2. MODPOST 1 modules CC /var/www/lkm/hello.mod.o LD [M] /var/www/lkm/hello.ko
使用insmod命令:
sudo insmod hello.ko
我们使用了printk()函数.会在syslog中打印.用tail /var/log/syslog查看
$ tail /var/log/syslog <snip> Apr 20 16:27:39 laptop kernel: [19486.347191] Hello world!
有一些发行版,内核信息会记录到别的文件,比如/var/log/messages.这个也要看syslog的配置.
使用rmmod 命令
sudo rmmod hello
查看syslog,可以看到模块卸载时候的输出:
$ tail /var/log/syslog <snip> Apr 20 16:29:23 laptop kernel: [19486.347191] Cleaning up module.
恭喜!你已经成功创建并使用了一个可加载内核模块.