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配置界面如下:


編譯完內核後,在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中。

       將開發板更新最新的文件系統後,我們就可以使用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]#
複製代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章