#include <linux/init.h> //包含init_module和cleanup_module的两个函数原型声明 #include <linux/kernel.h> //包含了printk函数的原型声明 #include <linux/module.h> /* 模块初始化函数 * 作用:在模块被动态加载到内核时被调用 */ static int __init vser_init(void) { printk("module init \n"); return 0; } /* 模块的清除函数 * 在模块从内核中卸除时被调用 */ static void __exit vser_exit(void) { printk("cleanup module\n"); } module_init(vser_init); //module_init是一个宏,用于指定init_module的函数别名为vers_init module_exit(vser_exit); //module_exit是一个宏,用于指定cleanup_module的函数别名为vers_exit MODULE_LICENSE("GPL"); //代表相应的许可证协议
注意:
1.几乎所有的驱动程序函数前都要加static关键字修饰的原因是为了避免和内核中已有的函数重名。
2.__init个__exit是对程序进行优化。因为初始化函数会且仅会被调用一次,所以该函数所占用的内存是可以被释放掉的。__init是把标记的函数放在ELF文件的特定代码段,在模块加载这些段时将会单独分配内存,这些函数调用成功后,模块的加载程序会释放这部分内存空间。__exit用于修饰清除函数。
Makefile
KERNEL_DIR = /home/linux-3.5 all: make -C $(KERNEL_DIR) M=`pwd` modules clean: make -C $(KERNEL_DIR) M=`pwd` clean obj-m += vser.o、
//将多个源文件编译生成一个内核模块
obj-m += vser.o
vser-objs = foo.o bar.o
编译驱动:make
加载驱动:insmod vser.ko
查看驱动加载:lsmod | grep vser
卸载驱动:rmmod vser
查看驱动打印信息:dmesg | tail