模塊的一些基礎知識
更新時間: 2007-05-30 10:33:16來源: 粵嵌教育瀏覽量:903
對Linux內核而言, 模塊是可有可無的特色。 這項特色必得在編譯內核時,選擇適當的選項才得以成功。 就我所知道的, 所有發行系統的內核,都是以模塊化定為預設選項的。
我們甚至于可以替系統設計新的模塊, 并且有內核載入執行,而不用重新編譯內核, 也不用重新啟動系統。
當一模塊載入內核時, 便成了內核的一部份, 因此:
這個模塊可以使用內核中所有的函數,而且可以存取所有的參數和數據結構。
這個模塊會以處理器層次的檔位來執行。 就 i386 的體系結構來說,就是第 0層的環 (ring level 0); 這么一來, 這個模塊就可以針對 I/O,做各式各樣的存取動作, 并執行一般程序所無法執行的指令。
模塊的代碼段和數據段, 都是直接映射到物理內存上去的,也就是說這種模塊不可能做"分頁 (paging)" 的動作。這么說來, 在模塊執行期間, 就不可能會產生分頁錯誤的問題了。
如同我們所看到的, 動態載入模塊已經有一些實時系統的特點:動態載入模塊, 會避免由分頁錯誤所造成的時間延遲,而且動態載入模塊, 可以存取所有的硬件資源。
模塊可以用 "C語言" 來寫。 這里舉個例子(要執行下面所提到的命令,是以 su、root 的身份登陸系統):
example1.c
#define MODULE
#include <linux/module.h>
#include <linux/cons.h>
static int output=1;
int init_module(void) {
printk("Output= %dn",output);
return 0;
}
void cleanup_module(void){
printk("Adi, Bye, Chao, Ovuar, n");
}
以下一行的參數來編譯 example1.c:
# gcc -I /usr/src/linux/include/linux -O2 -Wall -D__KERNEL__ -c example1.c
選項 -c 是要求 gcc 在產生目標文件之后就停下來,不要再做連接的動作了。 的結果是一個目標文件, example1.o。
內核缺少標準輸出函數, 因此我們不可以用 printf() 這個函數,而要以內核所提供的 printk()函數來代替。 printk() 和 printf() 幾乎沒有什么兩樣, 的差別是 printk() 會把輸出的結果,送到內核的環緩沖區 (ring buffer)里面。這個緩沖區是系統所有信息集中的地方, 就像開機時所看到的信息,都可以在這個環緩沖區找到。 任何時候, 我們都可以用 dmseg 命令查看環緩沖區的內容, 或是直接檢驗 /proc/kmsg 這個文件。
注意到這個模塊里并沒有main() 函數, 反而有個不帶任何參數的 init_module()函數。 cleanup_module() 是一個釋放模塊前,所必須呼叫的函數。 insmod 是用來載入模塊,然后執行模塊的。
# insmod example1.o
現在我們已經安裝好 example1 模塊了, 而且也執行了 example1 的 init_module()函數。 要看結果, 請用下列的命令:
# dmesg | tail -1
Output= 1
命令 lsmod 會列出當前所有載入核心中的模塊:
# lsmod
Module Pages Used by:
example1 1 0
sb 6 1
uart401 2 [sb] 1
sound 16 [sb uart401] 0 (autoclean)
呢,我們用 rmmod 來釋放模塊:
# rmmod example1
# dmesg | tail -2
Output= 1
Adi, Bye, Chao, Orvua,
dmesg 顯示了函數 cleanup_module() 已經執行了。
現在我們只差還不知道怎么把參數傳遞給模塊了。 這個方法出奇的簡單,只要指定數值給參數, 再由 insmod 把參數傳遞給模塊就行了。例如:
# insmod ejemplo1.o output=4
# dmesg | tail -3
Output= 1
Ads, Bye, Chao, Orvua,
Output= 4
現在模塊大大小小的事情該知道的都知道了,還愣著干什么,趕緊學著寫一個??!