有时,可以从逻辑上把内核模块分成几个源文件,在这种情况下,你需要做以下事情:
(1) 除了一个源文件外,在其他所有的源文件中都要增加一行 #define
__NO_VERSION__,这是比较重要的,因为 module.h通常包括了对kernel_version的定义,kernel_version是一个具有内核版本信息的全局变量,并且编译模块时要用到它。如果你需要version.h,你就必须自己包含它,但如果你定义了 __NO_VERSION__,module.h就就不会被包含进去。
(2) 像通常那样编译所有的源文件。
(3) 把所有的目标文件结合到一个单独文件中。在x86下,这样连接:
ld -m
elf_i386 -r -o <name of module>.o <第1个源文件>.o <第2个源文件>.o
请看下面例子start.c
/* start.c
*
*
"Hello, world"
* 这个文件包含了启动例程
*/
/*下面是必要的头文件
*/
/* 内核模块的标准形式*/
#include <linux/kernel.h>
#include <linux/module.h>
/* 处理CONFIG_MODVERSIONS
*/
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
/* 初始化模块 */
int init_module()
{
printk("Hello, world - this is the kernel
speaking\n");
return 0;
}
另一个例子 stop.c
/* stop.c */
/* 这个文件仅仅包含
stop 例程。*/
/* 必要的头文件*/
#include <linux/kernel.h>
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
void cleanup_module()
{
printk("Short is the life of a kernel module\n");
}
下面是多个文件的Makefile
CC=gcc
MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX
hello.o: start.o
stop.o
ld -m elf_i386 -r -o hello.o start.o stop.o
start.o: start.c
/usr/include/linux/version.h
$(CC)
$(MODCFLAGS) -c start.c
stop.o: stop.c
/usr/include/linux/version.h
$(CC)
$(MODCFLAGS) -c stop.c
“hello” 是模块名,它占用了一页(4K)的内存,此时,没有其它内核模块依赖它。要从内核移走这个模块,敲入“rmmod hello”,注意,rmmod命令需要的是模块名而不是文件名。其它实用程序的使用可参看相关的文挡。
关于模块编程更多的内容我们将在后续章节继续讨论。