在類unix操作系統中,驅動加載方式一般分爲:靜態加載和動態加載。靜態加載就是把驅動程序直接編譯到內核裏,系統啓動後直接被調用。靜態加載的缺點是調試起來比較麻煩,每次修改一個地方都要重新編譯下載內核,效率較低。動態加載利用了LINUX的module特性,可以在系統啓動後用insmod命令把驅動程序(.ko文件)添加上去,在不需要的時候用rmmod命令來卸載。下面我們通過蜂鳴器驅動實例分別對其進行詳述。
1.1.1
靜態加載
第一步:在kernel/drivers/char目錄下新建目錄beep,在beep目錄下創建Kconfig,Makefile以及x4412-beep.c三個文件。
第二步:編輯Makefile內容如下:
編輯Kconfig內容如下:
再編輯x4412-beep.c文件,其部分源碼如下:
第三步:在kernel/drivers/char/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目錄:
這時我們在任意目錄下即可執行如下指令加載驅動了:
我們可以看到打印信息“x4412 beep driver”,它就是蜂鳴器驅動的module_init加載的函數執行的打印信息,表明驅動已經正常運行。
可以使用lsmod命令查看已經加載的KO文件:
我們可以進一步驗證驅動是否加載,可以看到/sys/devices/platform目錄下是否有x4412-beep目錄生成:
可以執行指令測試蜂鳴器是否鳴叫:
如果還不信,使用如下指令卸載驅動後,然後再執行上面的測試指令查看結果。
2. 使用modprobe加載驅動
前面我們提到,modprobe並不需要指定到具體的KO文件目錄,我們不仿測試下:
這裏提示找不到/lib/modules目錄,和前面介紹的一樣,它需要在指定目錄下加載KO,那我們不仿新建該目錄,再執行上面的指令測試:
這裏提示找不到3.0.15-9tripod目錄,它對應linux內核的名稱,可以使用uname–r指令查詢。我們繼續新建目錄,繼續測試:
這時,提示找不到modules.dep文件。我們不需要手動創建該文件,使用depmod指令即可自動生成。很有可能默認情況下根文件系統不支持該指令,執行時會提示如下信息:
我們可以通過配置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命令後,該目錄下將會生成三個文件:
我們再嘗試執行modprobe指令加載驅動:
這裏提示在modules.dep文件中沒有發現我們加載的ko文件,我們嘗試查看一下modules.dep的內容:
可見,裏面的內容爲空。實際上,depmod指令會自動分析/lib/modules/$(uname -r)目錄下的可加載模塊,並按照固定的格式填入modules.dep中。因此,我們可以先將需要加載的ko文件拷貝到對應的目錄,再執行depmod指令。
可以看到,在modules.dep中已經存在有我們需要加載的ko文件名了。注意,不要手工的去編輯modules.dep文件!再執行modprobe指令,即可加載模塊了。