无
分类: LINUX
2010-04-21 20:45:39
一、模块形式
2.4内核的模块驱动程序有两种形式:
Sample1
#define MODULE /*2.4内核中应该在包含module.h文件前定义MODULE*/
#include
#include
int int_module(void)
{
printk(“hello,world\n”);/*在init_module函数中完成模块的初始化和加载*/
return 0;
}
void cleanup_module(void)
{
printk(“Goodbye, crul world\n”);/*在cleanup_module函数中完成模块的卸载*/
}
Sample2
#define MODULE /*2.4内核中应该在包含module.h文件前定义MODULE*/
#include
#include
static int hello_init(void)
{
printk(“Hello,world\n”);
return 0;
}
static void hello_exit(void)
{
printk(“Goodbye, crul world\n”);
}
module_init(hello_init);
module_exit(hello_exit);
第二个2.4内核中的模块形式和2.6内核中的模块驱动形式很相似,这是因为从内核版本2.4以后已经开始支持内核版本2.6.X上所用的模块形式了,2.6.X上所用的模块仍然可以在内核2.4内核版本上使用。
2.6内核的模块驱动程序形式:
#include
#include
#include
static int hello_init(void)
{
printk(“Hello,world\n”);
return 0;
}
static void hello_exit(void)
{
printk(“Goodbye, crul world\n”);
}
module_init(hello_init);// 必须!!
module_exit(hello_exit);// 必须!!
MODULE_LICENSE(“Dual BSD/GPL”); /*2.6内核中模块许可证声明是必须的,否则将出错*/
二、编译
2.4内核中,模块的编译只需要内核源码头文件,在包含module.h之前定义MODULE,编译链接后生成的模块后缀为.o文件;2.6内核中模块的编译需要配置过的内核源码,编译链接生成的模块后缀为.ko文件,编译过程会首先到内核源码目录,读取顶层的Makefile文件然后返回到模块源码所在目录中。
2.4内核模块的Makefile文件编译时用-c标记,只作编译不作链接,可以直接用gcc加上相应的选项后以命令行式编译(gcc -D__KERNEL__ -DMODULE -DLINUX -I/usr/local/src/linux2.4/include -c hello.c),但是为了减少失误以及方便以后再用,还是尽量使用Makefile。
KERNELDIR = /kernel/linux-2.4.26/
CFLAGS = -D__KERNEL__ -DMODULE –I$(KERNELDIR)/include -O2 -c
CC = gcc #交叉编译时换成arm-linux-gcc
all:=test.o
test.o:test.c
$(CC) $(CFLAGS) test.c
clean:
rm –rf *.o
2.6内核的驱动程序的编译Makefile比内核2.4中的有所不用
ifneq ($(KERNELRELEASE),)
mymodule-objs := test.o
obj-m :=test.o #obj-m:= test.o是必须的
else
PWD := $(shell pwd)
KERNELDIR := /kernel/linux-2.6.24/ #内核源码目录
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*
endif
用insmod加载后如果Shell没输出,执行tail /var/log/messsages (dmesg也可以)查看输出信息。
当加载时出现:"insmod: error inserting 'hello.ko': -1 Invalid module format"提示时,说明你所用的内核源码版本和自己的PC机上的不一致,所以如果要在本机上测试,那就用本机的内核源码吧,Makefile中KERNELDIR := /kernel/linux-2.6.24/改为:
KVAR :=$(shell uname -r)
KERNELDIR := /lib/modules/$(KVAR)/build
如果要交叉编译2.6内核的模块驱动程序中,怎么实施呢?我发现照样可以用这个Makefile来编译,此时只要所用到的内核源码顶层Makefile已经配置好了ARCH=arm和CROSS_COMPILE=/usr/local/arm/3.4.1/bin/arm-linux-,且这个内核源码最好是已经交叉编译成功过的。
KERNELRELEASE为内核源码顶层Makefile中定义的一个变量,在第一次读取执行些Makefile时,KERNELRELEASE是没有定义的,所以make将读取执行else之后的内容。-C $(KERNELDIR)指明跳转到内核源码读取Makefile,M=$(PWD)指明返回当前目录继续读入执行当前的Makefile。当从内核源码返回时,KERNELRELEASE已经被定义,Kbuild也被启动来解析Kbuild语法语句,make将继续读取else之前的内容。Else之前的内容为Kbuild语法的语句,指明模块源码中各个文件的依赖关系,以及生成的目标模块名。推荐使用M,而不是SUBDIRS,回为SUBDIRS是较为陈旧的做法。
三、总结
当然,2.6内核模块驱动程序和2.4内核的模块驱动程序的区别远不止这些,我只在些分析一下他们的形式差别和Makefile的不同写法。不足之处,请高后指点。