如果想要在Linux内核上扩展功能,有两条路可选,一是将自己的模块编译进Kernel,使模块成为内核的一部分;一是以模块的方式供内核加载。前者高效后者灵活,各有所长。以内核模块加载到内核是大多数设备驱动所采用的方式。关于模块的编译的方法在这里详细讨论一下。只针对2.6内核,还没看其他版本的实现方法,不知道 Linux2.6以前是不是这样的。
本人测试环境: RedHat as4 ( kernel:2.6.9-5 );
GCC ( version 3.4.3 );
make ( 3.80 )
将自己的模块编译进内核的详细步骤:
将自己的模块编译进内核,是写设备驱动的第一步。
首先要准备一分完整的正确的源码树,没有的可以在 上下载,或者找到安装盘将源码包安装上。
现在假若你有了一份源码树在相应的目录。开始写自己的模块:如果你想我一样懒,那就COPY一下吧。
1 #include <linux/init.h>
2 #include <linux/module.h>
3
4
5 static __init int test_init(void)
6 {
7 printk(KERN_ALERT"Test module is ready...\n");
8 return 0;
9 }
10
11
12 static __exit void test_exit(void)
13 {
14 printk(KERN_ALERT"Test module is exit ...\n");
15 return ;
16 }
17
18
19 module_init(test_init);
20 module_exit(test_exit);
21
22 MODULE_LICENSE("Dual BSD/GPL");
23 MODULE_AUTHOR("Singyea");
24 MODULE_DESCRIPTION("This is a simple module");
25 MODULE_VERSION("Ver 0.1");
保存为test.c 就是一个最简单的模块了,只有内核模块加载执行函数test_init()和模块卸载执行函数 test_exit()。还有一些关于模块的信息:
所使用的许可声明,作者,版本,描述等,这些信息等编译成模块后可以用 modinfo 命令得到。
将test.c copy到内核源码树中。这里的例子放到了/usr/src/kernels/2.6.9-5.EL-i686/drivers/char 下,就把它当作一个字符设备吧。呵呵
然后修改 /usr/src/kernels/2.6.9-5.EL-i686/drivers/char下的 Kconfig 文件
在 menu "Character devices" 下增加 一个config项,就叫 TEST吧。
例:
menu "Character devices"
config TEST_MODULES
tristate TEST
default m
---help---
This is a example
...
...
...
保存退出。
然后在 /usr/src/kernels/2.6.9-5.EL-i686/drivers/char下的 Makefile 文件里
增加一个对象,例:
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_ESPSERIAL) += esp.o
obj-$(CONFIG_TEST) += test.o //新增加
obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o
这样一个新的模块就可以被内核所提供的编译系统所认识了。
进入 图形配置界面:makemenuconfig .在
Device Drivers --->
Character devices --->
下可以看到自己所加的模块。选 M 编译成独立模块,选 * 编译进内核,空表示不进行编译。根据自己的需要对内核进行裁减
具体内容可以参照金步国的文档,N经典啊。
配置好之后就可以进行 内核及模块的编译了
make
make modules
还有一个简单的方法:
对于只想测试一个模块编写的是否正确而进行全部编译。感觉是不是太 “杀鸡用牛刀”啦 ?确实,牛人们也认识到这一点了,
就产生了另一种编译独立模块的方法。
还拿上面的例子来说 。写好之后,放在了某个文件夹下。比如在 /root/LinuxDrivers/下 这里只用编写一个 Makefile文件就可以了
在同一文件下创建如下Makefile文件:
[root@SingyeaLinux test]# vi Makefile