linux 2.4的动态模块是.o结尾,不是.ko 1.1 example1 #define MODULE #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> 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 <linux/module.h> 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 <linux/kernel.h> #include <linux/module.h> 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用于查看目标文件的信息 |
|