分类: LINUX
2009-10-09 10:13:03
1.1 example1
#define MODULE
#include
#include
#include
MODULE_LICENSE("GPL");
static int __init lkp_init(void)
{
printk("<1>hello world from the kernel space.. \n");
return 0;
}
static void __exit lkp_cleanup(void)
{
printk("<2>goodbye world, leaving kernel space.. \n");
}
module_init(lkp_init);
module_exit(lkp_cleanup);
以上是源代码,在2.4内核中动态可加载模块文件开始出一定要有一个MODULE宏定义,不然会出现版本不匹配等错误,
宏__init告知编译程序相关的函数和变量只用于初始化,编译程序将标有__init的所有代码存储到特殊的内存中,初始化结束后就释放这段内存,同样宏__exit和__exitdata仅用于退出和关闭例程,
代码中的最后两行module_init(lkp_init);module_exit(lkp_cleanup);可以不用加入,但这样的话模块在加入和移除时将不会调用lkp_init, lkp_cleanup,则文件/var/log/message中将不包含提示信息,如果不想使用这种方法,可以使用下面的代码
1.2 example2
#define MODULE
#include
MODULE_LICENSE("MYGPL");
int init_module(void)
{
printk("<1>Hello, world\n");
return 0;
}
void cleanup_module(void)
{
printk("<1>Goodbye cruel world\n");
}
在此代码中可以直接将example1中的初始化和退出函数名字直接改为init_module和cleanup_module,这样内核在加载和移除该模块时自动调动初始化和清除函数.
1.3 example3
#define MODULE
#include
#include
MODULE_LICENSE("GPL");
int init_module(void)
{
printk("<1>hello \n");
return 0;
}
void cleanup_module(void)
{
printk("<1>bye \n");
}
1.4 makefile文件
#Makefile for linux loadable kernel module
CC=gcc
CFLAG := -I/usr/src/linux-
OBJ=test
$(OBJ).o:$(OBJ).c
-rm $@ -f
$(CC) $(CFLAG) -c $(OBJ).c -o test.o
注意其中的gcc选项一定要包含D_KERNEL__
和D__MODULE这两个选项,不管对于什么的架构,一定要使gcc在编译时的环境版本和运行时的环境版本相匹配,也即在运行环境中,假如你使用ARM或者
MODULE_LICENSE("GPL");本句代码可以不要,但不要的话,运行时会出现"hello: module license 'unspecified' taints kernel.",词典上对taints的解释是"感染,污点".
1.5 编译过程
在命令行输入make命令编译生成ELF文件,
insmod hellomod来加载模块
rmmod hellomod移除hellomod模块
lsmod查看当前已加载模块
hellomod向模块发出的信息可以在/var/log/message文件中查看到,
可用dmesg命令来查看
readelf和ojbdump用于查看目标文件的信息