1、模块驱动描述
1)模块本身不被编译入内核映像,从而控制了内核的大小
2)模块一旦被加载,它就和内核中的其他部分完全一样
2、实验步骤
1) 解压原厂提供的 linux-3.0.35 内核
$ tar xf linux-3.0.35.tar.bz2
2)建立一个专门用于编写驱动模块的目录,该目录不在内核目录中
$ mkdir s-module
3)进入该模块目录进行 hello world 驱动模块的编写
$ cd s-module
$ emacs hello.c &
hello world 驱动模块的内容如下:
#include <linux/init.h> #include <linux/module.h> static int __init hello_init(void) { printk(KERN_ALERT "Hello World "); return 0; } static void __exit hello_exit(void) { printk(KERN_ALERT "Saya, Hello World ! "); } module_init(hello_init); module_exit(hello_exit); MODULE_AUTHOR("Rex <Rex@fk.com>"); MODULE_DESCRIPTION("hello world driver"); MODULE_LICENSE("GPL");
这个最简单的内核模块只包含内核模块加载函数,卸载函数和对GPL许可权限的声明以及一些描述信息。
4)linux 内核模块程序结构
- 模块加载函数 (程序中 module_init 中传入的函数)
当通过insmod或modprobe 命令加载到内核模块时,模块的加载函数会自动被内核执行。
- 模块卸载函数(程序中 module_exit 中传入的函数)
当通过rmmod 命令卸载某模块时,模块的卸载函数会自动被内核执行。
- 模块许可证声明
许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将会收到内核的警告
信息(kernel tainted)
通常来说模块卸载函数要完成与模块加载函数相反的功能,如下示:
- 若模块加载函数注册了xxx,则模块卸载函数应注销xxx
- 若模块加载函数动态申请了内在,则模块卸载函数应释放该内存
- 若模块加载函数申请了硬件资源(DMA,中断,I/O端口,I/O内存)的占用,则模块卸载函数应释放这些硬件资源
- 若模块加载函数开启了硬件,则卸载函数中一般要关闭
5)模块的编译
通过编写Makefile 由make来完成模块的编译工作,Makefile与hello.c在相同目录下,具体内容如下:
KDIR=/home/xxx/s-linux-3.0.35 PWD:=$(shell pwd) # kernel modules obj-m := hello.o modules: make -C $(KDIR) M=$(PWD) modules clean: rm -rf *.o *.ko *.mod.c *.markesr *.order *.symvers .PHONY:modules clean
6)模块的编译及遇到的问题
直接在s-module 目录下进行 make,出现如下错误提示:
ERROR: Kernel configuration is invalid. include/generated/autoconf.h or include/config/auto.conf are missing. Run 'make oldconfig && make prepare' on kernel src to fix it.
解决方法:编译生成内核后再编译模块
先进入内核根目录,进行如下操作:
s-linux-3.0.35$ make distclean s-linux-3.0.35$ make imx6_defconfig s-linux-3.0.35$ make uImage
然后再进入模块目录,编译模块,如下:
s-module$ make s-module$ ls hello.c hello.mod.c hello.o modules.order hello.ko hello.mod.o Makefile Module.symvers
7)注册hello 驱动模块至 I.Mx6 开发板
目前开发板挂载的是 nfs 文件系统,将hello.ko复制到该nfs 系统中的 /root 下
在开发板上执行,有如下提示:
root@freescale ~$ insmod hello.ko hello: version magic '3.0.35-2666-gbdde708 SMP preempt mod_unload modversions ARMv7 ' should be '3.0.35-gae4624f-dirty SMP preempt mod_unload modversions ARMv7 p2v8 ' insmod: can't insert 'hello.ko': invalid module format
错误原因:模块驱动的版本信息与内核的版本信息不匹配,开发板加载的内核不是刚刚编译的内核
解决办法:将新编译好的uImage 内核放至tftp根目录下(开发板通过tftp下载内核),开发板执行
root@freescale ~$ reboot
系统启动之后再执行加载操作:
root@freescale ~$ insmod hello.ko Hello World root@freescale ~$ rmmod hello.ko Saya, Hello World !