Linux 有許多功能是通過模組的方式, 在需要時才載入 kernel。 如此可使 kernel 較為精簡,進而提高效率,以及保有較大的彈性。這些可動態載入的模組,通常是系統的裝置驅動程式。載入模組採用 insmod 指令,其常用文法如下。
insmod [-fkmpsvxX] [-o<模組名稱>] [模組檔案]
其中的參數解釋如下。
-f:不檢查目前 kernel 版本與模組編譯時間的 kernel 版本是否一致,強制將模組載入。
-k:將模組設定為自動卸載。
-m:輸出模組的載入資訊。
-p:測試模組是否能正確地載入 kernel。
-s:將所有資訊記錄在系統記錄檔案中。
-v:執行時顯示詳細的資訊。
-x:要匯出模組的外部符號。
-X:匯出模組所有的外部符號,此為預設定。
• rmmod(卸載模組)指令
Linux 把系統的許多功能編譯成一個個單獨的模組,待有需要時再分別載入它們,如果不再需要這些模組的時候,就可以使用 rmmod 命令來卸載這些模組。其文法如下。
rmmod [-as] [模組名稱...]
其使用參數說明如下。
-a:刪除所有目前不需要的模組。
-s:把資訊輸出至 syslog 常駐服務,而非終端機介面
/* hello.c */
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, World/n");
return 0;
}
static int hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world/n");
}
module_init(hello_init);
module_exit(hello_exit);
這個模組什麼也不幹,只是在模組載入時列印一條資訊,卸載時也列印一條資訊。麻雀雖小,但五髒具全,MODULE_LICENSE()指明認證方式,現在支援的有:“GPL” “GPL v2" "GPL and additional rights" "Dual BSD/GPL" "Dual MIT/GPL" "Dual MPL/GPL" "Proprietary",這是核心2.6裡新添加的,實驗發現它不是必需的。module_init()指明模組的入口,這是必需的;module_exit()指明模組的出口,這也是必需的。
編譯使用make的擴充功能,在與hello.c同一目錄下建立一個
Makefile檔案,內容如下:
/* Makefile */
TARGET=hello
KDIR=/usr/src/linux-headers-2.6.31-19-generic
PWD=$(shell pwd)
obj-m:=$(TARGET).o
default:
make -C $(KDIR) M=$(PWD) modules
其中TARGET指明了目標檔案的名字,KDIR指明了引用標頭檔的位置,請根據具體情況修改該檔案。不過有幾點要說明,模組的編譯需要有一個核心源碼的目錄結構,如果有核心源碼當然更好,直接把KDIR改為源碼的路徑就OK了。當然只有一個核心目錄結構也就可以了,畢竟需要的只是標頭檔,及一些編譯指令碼,在Linux各發行版的/usr/src/下是有這樣一個目錄結構的,比如我的系統為Ubuntu9.10,核心為2.6.31-19的通用版,在/usr/src/下就有linux-headers-2.6.31-19-generic這樣一個目錄。所以我使用KDIR=/usr/src/linux-headers-2.6.31-19-generic。其實還有一個目錄名為linux-headers-2.6.31-19,而且你會發現linux-headers-2.6.31-19-generic裡的大部分檔案只是指向linux-headers-2.6.31-19的一些連結,不過linux-headers-2.6.31-19裡面預設缺少一些編譯模組所需要的檔案,不要使用它。
接下來,你只要使用make命
令,就可以進行編譯了,make會為你處理好一切,它會根據KDIR找到編譯所需要的檔案。如果你運氣好的話,你的目前的目錄下就會成生hello.o
hello.mod.o hello.mod.c modules.order Module.markers Module.symvers
hello.ko,當然可愛的hello.ko就是我們想要的。到此你的模組已經成功產生了,接下來便可以載入這個模組看看效果了。
使用
insmod ./hello.ko來載入模組,如果你遇到insmod: error inserting 'hello.o' :-l
invalid module
format這樣的錯誤,不用驚慌,並不是你的模組有問題,而是你當前啟動並執行核心版本與你編譯連結的標頭檔版本不一致,所以會出現格式不對的問題。此時,
你可以更換系統核心,也可以下載一個與系統版本一致的核心源碼重新編譯該模組。如果你沒有遇到任何問題,也沒有列印出任何資訊,那麼恭喜你,你的核心載入
成功了,你可以使用lsmod命令來羅列出當前你系統載入的所有模組,相信你在列表中會找到hello的。你可能會疑惑,為什麼沒有如我們想像中的那樣,
列印出"Hello,
World"?呵呵,這是因為printk並不會把列印內容列印到你當面的終端,要知道模組是運行在核心態的,而你所能面對的是使用者態,核心態的列印資訊
需要通過log或者dmesg命令來查看,想看到列印結果,最簡單的方法是敲入dmesg命令,你就可以看到你所希望看到的資訊了,同時,你也可以開啟
/var/log/message這個檔案進行查看。
最後,使用rmmod
hello來卸載模組,同樣,使用dmesg可以看到列印出的"Goodbye, cruel world"。