modprobe加载驱动问题


在类unix操做系统中,驱动加载方式通常分为:静态加载和动态加载。静态加载就是把驱动程序直接编译到内核里,系统启动后直接被调用。静态加载的缺点是调试起来比较麻烦,每次修改一个地方都要从新编译下载内核,效率较低。动态加载利用了LINUX的module特性,能够在系统启动后用insmod命令把驱动程序(.ko文件)添加上去,在不须要的时候用rmmod命令来卸载。下面咱们经过蜂鸣器驱动实例分别对其进行详述。
1.1.1    静态加载
第一步:在kernel/drivers/char目录下新建目录beep,在beep目录下建立Kconfig,Makefile以及x4412-beep.c三个文件。
第二步:编辑Makefile内容以下:
  1. obj-$(CONFIG_X4412_BEEP_DRIVER) += x4412-beep.o
复制代码
编辑Kconfig内容以下:
  1. config X4412_BEEP_DRIVER
  2.          bool "X4412 beep driver"
  3.          default y
  4.          help
  5.          compile for x4412 beep driver,y for kernel,m for module.
复制代码
再编辑x4412-beep.c文件,其部分源码以下:
  1. static int __devinit x4412_beep_init(void)
  2. {
  3.          int ret;

  4.          printk("x4412 beep driver\r\n");

  5.          ret = platform_device_register(&x4412_beep_device);
  6.          if(ret)
  7.                    printk("failed to register x4412 beep device\n");

  8.          ret = platform_driver_register(&x4412_beep_driver);
  9.          if(ret)
  10.                    printk("failed to register x4412 beep driver\n");

  11.          return ret;
  12. }

  13. static void x4412_beep_exit(void)
  14. {
  15.          platform_driver_unregister(&x4412_beep_driver);
  16. }

  17. module_init(x4412_beep_init);
  18. module_exit(x4412_beep_exit);

  19. MODULE_LICENSE("GPL");
  20. MODULE_AUTHOR("www.9tripod.com");
  21. MODULE_DESCRIPTION("x4412 beep driver");
复制代码
        第三步:在kernel/drivers/char/Kconfig 中添加以下语句:
  1. source "drivers/char/beep/Kconfig"
复制代码
        第四步:在kernel/drivers/char/Makefile 中添加以下语句:
  1. obj-y                             += beep/
复制代码

       第五步:配置menuconfig,编译内核。menuconfig配置界面以下:linux


编译完内核后,在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目录:
  1. [root@x4412 ~]# mount /dev/mmcblk1p1 /mnt/
  2. [root@x4412 ~]# ls /mnt/
  3. Alarms/                   Notifications/            camera.smdk4x12.so*
  4. DCIM/                     Pictures/                 camera.smdk4x12.so.rp*
  5. Download/                 Podcasts/                 sdfuse/
  6. LOST.DIR/                 Ringtones/                x4412-android/
  7. Movies/                   SimpleDoubleWebCams2.apk* x4412-beep.ko*
  8. Music/                    UvcWebCam.apk*            x4412-qt/
  9. NIKON001.DSC*             and-TPnp-vstarcam.apk*    x4412_ibox_led*
  10. [root@x4412 ~]#
复制代码
    这时咱们在任意目录下便可执行以下指令加载驱动了:
  1. [root@x4412 ~]# insmod /mnt/x4412-beep.ko
  2. [  115.612694] x4412 beep driver
  3. [root@x4412 ~]#
复制代码
    咱们能够看到打印信息“x4412 beep driver”,它就是蜂鸣器驱动的module_init加载的函数执行的打印信息,代表驱动已经正常运行。
    可使用lsmod命令查看已经加载的KO文件:
  1. [root@x4412 ~]# lsmod
  2. Module                  Size  Used by    Not tainted
  3. x4412_beep              2099  0
  4. [root@x4412 ~]#
复制代码
    咱们能够进一步验证驱动是否加载,能够看到/sys/devices/platform目录下是否有x4412-beep目录生成:
  1. [root@x4412 ~]# ls /sys/devices/platform/x4412-*
  2. /sys/devices/platform/x4412-Oops:
  3. Oops       driver@    modalias   power/     subsystem@ uevent

  4. /sys/devices/platform/x4412-beep:
  5. driver@    modalias   power/     state      subsystem@ uevent
  6. [root@x4412 ~]#
复制代码
    能够执行指令测试蜂鸣器是否鸣叫:
  1. [root@x4412 ~]# echo 1 > /sys/devices/platform/x4412-beep/state
复制代码
    若是还不信,使用以下指令卸载驱动后,而后再执行上面的测试指令查看结果。
  1. [root@x4412 ~]# rmmod /mnt/x4412-beep.ko
  2. [root@x4412 ~]#
  3. [root@x4412 ~]# lsmod
  4. Module                  Size  Used by    Not tainted
  5. [root@x4412 ~]#
复制代码
2.     使用modprobe加载驱动
前面咱们提到,modprobe并不须要指定到具体的KO文件目录,咱们不仿测试下:
  1. [root@x4412 /]# modprobe x4412-beep.ko
  2. modprobe: can't change directory to '/lib/modules': No such file or directory
  3. [root@x4412 /]#
复制代码
这里提示找不到/lib/modules目录,和前面介绍的同样,它须要在指定目录下加载KO,那咱们不仿新建该目录,再执行上面的指令测试:
  1. [root@x4412 /]# mkdir /lib/modules
  2. [root@x4412 /]# modprobe x4412-beep.ko
  3. modprobe: can't change directory to '3.0.15-9tripod': No such file or directory
  4. [root@x4412 /]#
复制代码
这里提示找不到3.0.15-9tripod目录,它对应linux内核的名称,可使用uname–r指令查询。咱们继续新建目录,继续测试:
  1. [root@x4412 /]# uname -r
  2. 3.0.15-9tripod
  3. [root@x4412 /]# mkdir /lib/modules/3.0.15-9tripod
  4. [root@x4412 /]# modprobe x4412-beep.ko
  5. modprobe: can't open 'modules.dep': No such file or directory
  6. [root@x4412 /]#
复制代码
这时,提示找不到modules.dep文件。咱们不须要手动建立该文件,使用depmod指令便可自动生成。颇有可能默认状况下根文件系统不支持该指令,执行时会提示以下信息:
  1. [root@x4412 modules]# depmod
  2. -sh: depmod: command not found
  3. [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中。
android

        将开发板更新最新的文件系统后,咱们就可使用depmod 指令了。在没有执行该指令时,在/lib/modules/ 3.0.15-9tripod 下是没有任何文件的,执行depmod 命令后,该目录下将会生成三个文件:
  1. [root@x4412 /]# ls /lib/modules/3.0.15-9tripod/
  2. [root@x4412 /]# depmod
  3. [root@x4412 /]# ls /lib/modules/3.0.15-9tripod/
  4. modules.alias    modules.dep      modules.symbols
  5. [root@x4412 /]#
复制代码
    咱们再尝试执行modprobe指令加载驱动:
  1. [root@x4412 /]# modprobe x4412-beep.ko
  2. modprobe: module x4412-beep.ko not found in modules.dep
  3. [root@x4412 /]#
复制代码
    这里提示在modules.dep文件中没有发现咱们加载的ko文件,咱们尝试查看一下modules.dep的内容:
  1. [root@x4412 /]# cd /lib/modules/3.0.15-9tripod/
  2. [root@x4412 3.0.15-9tripod]# more modules.dep
  3. [root@x4412 3.0.15-9tripod]#
复制代码
    可见,里面的内容为空。实际上,depmod指令会自动分析/lib/modules/$(uname -r)目录下的可加载模块,并按照固定的格式填入modules.dep中。所以,咱们能够先将须要加载的ko文件拷贝到对应的目录,再执行depmod指令。
  1. [root@x4412 3.0.15-9tripod]# pwd                  
  2. /lib/modules/3.0.15-9tripod
  3. [root@x4412 3.0.15-9tripod]# cp /mnt/x4412-beep.ko .
  4. [root@x4412 3.0.15-9tripod]# depmod
  5. [root@x4412 3.0.15-9tripod]# more modules.dep
  6. x4412-beep.ko:
  7. [root@x4412 3.0.15-9tripod]#
复制代码
    能够看到,在modules.dep中已经存在有咱们须要加载的ko文件名了。注意,不要手工的去编辑modules.dep文件!再执行modprobe指令,便可加载模块了。
  1. [root@x4412 3.0.15-9tripod]# modprobe x4412-beep.ko
  2. [ 2029.489772] x4412 beep driver
  3. [root@x4412 3.0.15-9tripod]#
复制代码