在类unix操作系统中,驱动加载方式一般分为:静态加载和动态加载。静态加载就是把驱动程序直接编译到内核里,系统启动后直接被调用。静态加载的缺点是调试起来比较麻烦,每次修改一个地方都要重新编译下载内核,效率较低。动态加载利用了LINUX的module特性,可以在系统启动后用insmod命令把驱动程序(.ko文件)添加上去,在不需要的时候用rmmod命令来卸载。下面我们通过蜂鸣器驱动实例分别对其进行详述。
1.1.1 静态加载
第一步:在kernel/drivers/char目录下新建目录beep,在beep目录下创建Kconfig,Makefile以及x4412-beep.c三个文件。
第二步:编辑Makefile内容如下:
- obj-$(CONFIG_X4412_BEEP_DRIVER) += x4412-beep.o
复制代码
编辑Kconfig内容如下:
- config X4412_BEEP_DRIVER
- bool "X4412 beep driver"
- default y
- help
- compile for x4412 beep driver,y for kernel,m for module.
复制代码
再编辑x4412-beep.c文件,其部分源码如下:
- static int __devinit x4412_beep_init(void)
- {
- int ret;
-
- printk("x4412 beep driver\r\n");
-
- ret = platform_device_register(&x4412_beep_device);
- if(ret)
- printk("failed to register x4412 beep device\n");
-
- ret = platform_driver_register(&x4412_beep_driver);
- if(ret)
- printk("failed to register x4412 beep driver\n");
-
- return ret;
- }
-
- static void x4412_beep_exit(void)
- {
- platform_driver_unregister(&x4412_beep_driver);
- }
-
- module_init(x4412_beep_init);
- module_exit(x4412_beep_exit);
-
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("www.9tripod.com");
- MODULE_DESCRIPTION("x4412 beep driver");
复制代码
第三步:在kernel/drivers/char/Kconfig
中添加如下语句:
- source "drivers/char/beep/Kconfig"
复制代码
第四步:在kernel/drivers/char/Makefile
中添加如下语句:
第五步:配置menuconfig,编译内核。menuconfig配置界面如下:
编译完内核后,在kernel/drivers/char/beep
目录下将会生成目标文件x4412-beep.o
,它会被打包到内核映像zImage
中。
1.1.1 动态加载
在前面的静态加载实验中,我们在menuconfig中尝试配置X4412 beep driver,发现只能选中或不选中,这是由beep目录下面的Kconfig文件决定的。我们发现,X4412 beep driver被声明的参数为bool。我们只需要将bool改为tristate,就可以配置成模块了。bool表示布尔类型,只允许选中或不选中;tristate为三态类型,允许选中,不选中以及编译成模块。修改后的配置界面如下:
保存配置之后再编译内核,这时我们发现,在kernel/drivers/char/beep目录下将会生成模块文件x4412-beep.ko。
将新生成的内核映像zImage烧写到开发板,进入/sys/devices/platform目录,我们发现已经没有x4412-beep目录了,有图为证:
linux设备驱动的动态加载可以使用insmod或modprobe两种方式,insmod一次只能加载一个特定的驱动,且需要驱动的绝对路径,而modprobe则可以一次性将有依赖关系的驱动全部加载到内核,不需要驱动的具体地址。但需要将驱动拷贝到/lib/modules/$(uname -r)/目录下,下面我们以前面的蜂鸣器驱动为例,分别介绍两种加载方法。
1. 使用insmod加载驱动
将前面生成的x4412-beep.ko文件拷贝到SD卡或U盘,并mount到/mnt目录:
- [root@x4412 ~]# mount /dev/mmcblk1p1 /mnt/
- [root@x4412 ~]# ls /mnt/
- Alarms/ Notifications/ camera.smdk4x12.so*
- DCIM/ Pictures/ camera.smdk4x12.so.rp*
- Download/ Podcasts/ sdfuse/
- LOST.DIR/ Ringtones/ x4412-android/
- Movies/ SimpleDoubleWebCams2.apk* x4412-beep.ko*
- Music/ UvcWebCam.apk* x4412-qt/
- NIKON001.DSC* and-TPnp-vstarcam.apk* x4412_ibox_led*
- [root@x4412 ~]#
复制代码
这时我们在任意目录下即可执行如下指令加载驱动了:
- [root@x4412 ~]# insmod /mnt/x4412-beep.ko
- [ 115.612694] x4412 beep driver
- [root@x4412 ~]#
复制代码
我们可以看到打印信息“x4412 beep driver”,它就是蜂鸣器驱动的module_init加载的函数执行的打印信息,表明驱动已经正常运行。
可以使用lsmod命令查看已经加载的KO文件:
- [root@x4412 ~]# lsmod
- Module Size Used by Not tainted
- x4412_beep 2099 0
- [root@x4412 ~]#
复制代码
我们可以进一步验证驱动是否加载,可以看到/sys/devices/platform目录下是否有x4412-beep目录生成:
- [root@x4412 ~]# ls /sys/devices/platform/x4412-*
- /sys/devices/platform/x4412-Oops:
- Oops driver@ modalias power/ subsystem@ uevent
-
- /sys/devices/platform/x4412-beep:
- driver@ modalias power/ state subsystem@ uevent
- [root@x4412 ~]#
复制代码
可以执行指令测试蜂鸣器是否鸣叫:
- [root@x4412 ~]# echo 1 > /sys/devices/platform/x4412-beep/state
复制代码
如果还不信,使用如下指令卸载驱动后,然后再执行上面的测试指令查看结果。
- [root@x4412 ~]# rmmod /mnt/x4412-beep.ko
- [root@x4412 ~]#
- [root@x4412 ~]# lsmod
- Module Size Used by Not tainted
- [root@x4412 ~]#
复制代码
2. 使用modprobe加载驱动
前面我们提到,modprobe并不需要指定到具体的KO文件目录,我们不仿测试下:
- [root@x4412 /]# modprobe x4412-beep.ko
- modprobe: can't change directory to '/lib/modules': No such file or directory
- [root@x4412 /]#
复制代码
这里提示找不到/lib/modules目录,和前面介绍的一样,它需要在指定目录下加载KO,那我们不仿新建该目录,再执行上面的指令测试:
- [root@x4412 /]# mkdir /lib/modules
- [root@x4412 /]# modprobe x4412-beep.ko
- modprobe: can't change directory to '3.0.15-9tripod': No such file or directory
- [root@x4412 /]#
复制代码
这里提示找不到3.0.15-9tripod目录,它对应linux内核的名称,可以使用uname–r指令查询。我们继续新建目录,继续测试:
- [root@x4412 /]# uname -r
- 3.0.15-9tripod
- [root@x4412 /]# mkdir /lib/modules/3.0.15-9tripod
- [root@x4412 /]# modprobe x4412-beep.ko
- modprobe: can't open 'modules.dep': No such file or directory
- [root@x4412 /]#
复制代码
这时,提示找不到modules.dep文件。我们不需要手动创建该文件,使用depmod指令即可自动生成。很有可能默认情况下根文件系统不支持该指令,执行时会提示如下信息:
- [root@x4412 modules]# depmod
- -sh: depmod: command not found
- [root@x4412 modules]#
复制代码
我们可以通过配置busybox来添加这个功能。但是我们制作的根文件系统,是用buildroot自动完成的,busybox也随之自动生成,我们还能随心所欲的添加其他功能吗?答案是肯定的。
进入buildroot的menuconfig菜单,进入Target packages选项,发现第一栏有关于busybox的配置选项,如下图所示:
可见,我们只需要配置完busybox
后,保存到这里就可以了。有两种方法可以实现,第一种就是在busybox
的编译目录配置完成后,用busybox
当前目录的配置文件.config
替换掉package/busybox/busybox.config
文件。第二种就是配置完busybox
后,直接在buildroot
的配置选项中导入这个配置文件。
busybox
的编译目录在output/build/busybox-1.22.1
下,这里output
是编译之后才会释放的文件,手工配置busybox
后,配置文件也会保存在这个目录下,因此不推荐用第二种方法,它不便于源码维护。下面介绍第一种方法。
进入output/build/busybox-1.22.1
目录,执行make menuconfig
,进入Linux Module Utilities
菜单,如下图所示:
选中insmod,rmmod,lsmod,modprobe,depmod,保存退出,然后将当前目录下的.config文件覆盖掉package\busybox\busybox.config文件,之后在buildroot根目录下执行make指令重新编译,busybox将会自动更新,并最终打包到映像文件rootfs.ext4中。
将开发板更新最新的文件系统后,我们就可以使用depmod
指令了。在没有执行该指令时,在/lib/modules/ 3.0.15-9tripod
下是没有任何文件的,执行depmod
命令后,该目录下将会生成三个文件:
- [root@x4412 /]# ls /lib/modules/3.0.15-9tripod/
- [root@x4412 /]# depmod
- [root@x4412 /]# ls /lib/modules/3.0.15-9tripod/
- modules.alias modules.dep modules.symbols
- [root@x4412 /]#
复制代码
我们再尝试执行modprobe指令加载驱动:
- [root@x4412 /]# modprobe x4412-beep.ko
- modprobe: module x4412-beep.ko not found in modules.dep
- [root@x4412 /]#
复制代码
这里提示在modules.dep文件中没有发现我们加载的ko文件,我们尝试查看一下modules.dep的内容:
- [root@x4412 /]# cd /lib/modules/3.0.15-9tripod/
- [root@x4412 3.0.15-9tripod]# more modules.dep
- [root@x4412 3.0.15-9tripod]#
复制代码
可见,里面的内容为空。实际上,depmod指令会自动分析/lib/modules/$(uname -r)目录下的可加载模块,并按照固定的格式填入modules.dep中。因此,我们可以先将需要加载的ko文件拷贝到对应的目录,再执行depmod指令。
- [root@x4412 3.0.15-9tripod]# pwd
- /lib/modules/3.0.15-9tripod
- [root@x4412 3.0.15-9tripod]# cp /mnt/x4412-beep.ko .
- [root@x4412 3.0.15-9tripod]# depmod
- [root@x4412 3.0.15-9tripod]# more modules.dep
- x4412-beep.ko:
- [root@x4412 3.0.15-9tripod]#
复制代码
可以看到,在modules.dep中已经存在有我们需要加载的ko文件名了。注意,不要手工的去编辑modules.dep文件!再执行modprobe指令,即可加载模块了。
- [root@x4412 3.0.15-9tripod]# modprobe x4412-beep.ko
- [ 2029.489772] x4412 beep driver
- [root@x4412 3.0.15-9tripod]#
复制代码