编写可加载模块

来源:互联网 发布:自学数学软件 编辑:程序博客网 时间:2024/04/29 21:05

Linux 2.6中的模块必须包含以下两个接口:

  1. module_init(your_init_func);//模块初始化接口  
  2. module_exit(your_exit_func);//模块卸载接口 

加载一个内核模块的命令是insmod,格式如下:
  1. #insmod modulename.ko 

卸载一个内核模块的命令是rmmod,格式如下:
  1. #rmmod modulename 

可加载模块的源代码可以放在内核代码树中,也可以独立于内核代码树。如果是后一种情况,就需要为可加载模块编写makefile文件。可加载模块的makefile文件最重要的就是配置如下几个变量:
  1. CC  = arm-linux-gcc  
  2. obj-m   :smodule.o  
  3. KERNELDIR ?= /mnt/v/linux-2.6.33.4  

CC是编译器,obj-m为需要编译的目标模块,KERNELDIR为内核路径。注意在编写可加载模块前先要有一个内核代码目录树。KERNELDIR的内核版本必须与运行的内核版本一致,否则编译出的模块往往无法加载。

例1.1  最简单的内核模块

代码见光盘\src\1drivermodel\1-1simple。核心代码如下所示:

  1. static int demo_module_init(void)  
  2. {  
  3.     printk("demo_module_init\n");  
  4.     return 0;  
  5. }  
  6. static void demo_module_exit(void)  
  7. {  
  8.     printk("demo_module_exit\n");  
  9. }  
  10. module_init(demo_module_init);  
  11. module_exit(demo_module_exit);  
  12.  
  13. MODULE_DESCRIPTION("simple module");  
  14. MODULE_LICENSE("GPL");  

模块运行在内核态,不能使用用户态C库函数中的printf函数,而要使用printk函数打印调试信息。编写一个makefile文件如下:
  1. AR  = ar 
  2. ARCH    = arm 
  3. CC  = arm-linux-gcc  
  4. DEBFLAGS = -O2  
  5. obj-m   :smodule.o  
  6. KERNELDIR ?= /mnt/v/urbetter-linux2.6.28-v1.0  
  7. PWD       := $(shell pwd)  
  8. modules:  
  9.     $(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules  
  10. clean:  
  11.     rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions  

执行make后生成smodule.ko。运行结果如下:
  1. [root@urbetter /home]#insmod  smodule.ko   
  2. demo_module_init  
  3. [root@urbetter /home]#rmmod smodule      
  4. rmmod: chdir(2.6.28.6): No such file or directory  
  5. [root@urbetter /home]#mkdir -p /lib/modules/`uname -r`  
  6. [root@urbetter /home]#cp smodule.ko /lib/modules/`uname -r`/smodule.ko  
  7. [root@urbetter /home]#rmmod smodule  
  8. demo_module_exit  

其中uname -r用来得到内核版本号。如果要使用rmmod命令卸载内核模块,必须在/lib/modules目录下的以内核版本号为名称的目录下建立相应的模块文件。从上面的结果看出,第一次运行rmmod smodule会失败。在建立模块文件后,再次运行rmmod smodule会成功。
0 0
原创粉丝点击