DKMS簡介

我們都知道,如果要使用沒有集成到內核之中的Linux驅動程序需要手動編譯。當然,這並不是一件什麼難事,即使是對於沒有編程經驗的Linux使用者,只要稍微有點hacker的意識,努力看看代碼包裏的Readme或者INSTALL文件,按部就班的執行幾條命令還是很容易辦到的。但這裏還有一個問題,Linux模塊和內核是有依賴關係的,如果遇到因爲發行版更新造成的內核版本的變動,之前編譯的模塊是無法繼續使用的,我們只能手動再編譯一遍。這樣重複的操作有些繁瑣且是反生產力的,而對於沒有內核編程經驗的使用者來說可能會造成一些困擾,使用者搞不清楚爲什麼更新系統之後,原來用的好好的驅動程序突然就不能用了。這裏,就是Dell創建的DKMS項目的意義所在。DKMS全稱是Dynamic Kernel Module Support,它可以幫我們維護內核外的這些驅動程序,在內核版本變動之後可以自動重新生成新的模塊。

在使用dkms之前首先需要確保系統中已經安裝了 DKMS。在Ubuntu下可以執行下面這個命令安裝:

sudo apt-get install dkms

安裝完畢之後,我們就可以開始使用 DKMS了。

本文的例子來自Ubuntu Wiki,大家可以從這裏下載。

使用DKMS編譯安裝內核模塊

DKMS的使用流程可以用下圖簡單表示:

以hello-0.1爲例,我們首先需要把代碼copy到"/usr/src"下面,這樣完整路徑將是"/usr/src/hello-0.1"。

DKMS要求我們的代碼目錄必須以" <module>-<module-version>"的格式命名。本例中,代碼的版本是0.1。

DKMS主要的命令可以參考上圖所示,分別是add、build、install、uninstall和remove,另外,還可以執行"dkms status"查看目前DKMS系統維護的模塊的狀態。

在我自己的主機上,首先執行dkms status看看:

bcmwl, 5.100.82.38+bdcom, 2.6.38-8-generic, i686: installed

目前我的機器上有一個處於“Installed State”的bcmwl模塊,這是我的Broadcom無線網卡驅動。

我們還可以在目錄"/var/lib/dkms"下查看目前有哪些由DKMS維護的驅動程序。

接下來,執行“sudo dkms add -m hello -v 0.1”來添加hello-0.1,執行的結果是:

Creating symlink /var/lib/dkms/hello/0.1/source ->                 /usr/src/hello-0.1
DKMS: add Completed.

我們再執行“dkms status”看看:

bcmwl, 5.100.82.38+bdcom, 2.6.38-8-generic, i686: installed
hello, 0.1: added

hello-0.1已經處於"Added State"了。

下面執行“sudo dkms build -m hello -v 0.1”:

Kernel preparation unnecessary for this kernel.  Skipping...
Building module:cleaning build area....
make KERNELRELEASE=2.6.38-8-generic all KVERSION=2.6.38-8-generic.....
cleaning build area....
DKMS: build Completed.

我們可以在目錄“/var/lib/dkms/hello/0.1/2.6.38-8-generic/i686/module/”下面找到編譯生成的hello.ko二進制模塊。

最後執行“sudo dkms install -m hello -v 0.1”來安裝hello.ko:

hello.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/2.6.38-8-generic/updates/dkms/

把hello.ko從/lib/modules下移除可以執行“sudo dkms uninstall -m hello -v 0.1”,甚至可以使用命令“sudo dkms remove -m hello -v 0.1 --all”把hello-0.1從/var/lib/dkms下徹底刪除,這樣,DKMS系統就不再維護hello-0.1模塊了。

以上的每個步驟我們都可以通過“dkms status”來查看執行後的狀態。

對於處於"Installed State"的模塊,即使內核版本發生變化,我們也不需要手動重新編譯內核了。

我們再回過頭來研究一下hello-0.1中文件。

/usr/src/hello-0.1/
├── dkms.conf
├── hello.c
└── Makefile

如果您比較熟悉Linux內核模塊的編寫,hello.c和Makefile的內容應該很簡單,本文不再詳細解釋。有一點需要注意,在Makefile中要使用變量$(KVERSION)指定內核版本號,這樣我們在執行dkms時,就可以用“-k”選項來設定爲哪個內核版本編譯模塊。

$(MAKE) -C /lib/modules/$(KVERSION)/build M=$(PWD) modules

dkms.conf文件是本文關注的重點。

PACKAGE_NAME="hello"
PACKAGE_VERSION="0.1"
CLEAN="make clean"
MAKE[0]="make all KVERSION=$kernelver"
BUILT_MODULE_NAME[0]="hello"
DEST_MODULE_LOCATION[0]="/updates"
AUTOINSTALL="yes"

PACKAGE_NAME和PACKAGE_VERSION和文件夾的命名是一致的。

CLEAN的命令是每次build的時候第一條執行的動作。

MAKE[0]用來設定編譯的命令,一般情況下是不用設定的。在本例中,就可以把MAKE[0]這行刪掉。但在下面這種情況下就需要設定了。比如,您的Makefile裏有多個target,分別爲all、debug、release等,不指定MAKE[0]時,編譯會選擇第一個target來執行,也就是make all,如果您想執行make release來編譯,就需要在dkms.conf裏明確設定。

BUILD_MODULE_NAME[0]用來指定模塊的名稱,一般情況下也可以不設定。

DEST_MODULE_LOCATION[0]用來設定模塊安裝的目的地址,本例是"/lib/module/$(KVERSION)/updates"。

AUTOINSTALL="yes"表示在Linux引導之後DKMS會自動對這個模塊執行Build和Install的動作,當然如果模塊已經處於該狀態的話,相應的動作是不用再執行的。

基於DKMS製作驅動程序的DEB安裝包

作爲Linux驅動開發者,有時候用戶會要求我們提供驅動的DEB安裝包,基於DKMS來製作DEB安裝包是一個很好的選擇。對開發者來說這樣的DEB包製作起來比較簡單,對於用戶來說使用起來也省去許多煩惱。需要注意的是,製作DEB包依賴於dh-make,請首先執行“sudo apt-get install dh-make”安裝。

在模塊處於"Built State"的條件下,執行“sudo dkms mkdeb -m hello -v 0.1”可以在目錄“/var/lib/dkms/hello/0.1/deb”下生成deb包。

另外,DKMS還提供了mktarball和mkrpm來製作tarball和RPM安裝包,這裏就不再一一贅述。



作者:wwang
出處:http://www.cnblogs.com/wwang
本文采用知識共享署名-非商業性使用-相同方式共享 2.5 中國大陸許可協議進行許可,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章