新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 什么是module 以及如何寫(xiě)一個(gè)module(轉(zhuǎn))

什么是module 以及如何寫(xiě)一個(gè)module(轉(zhuǎn))

作者: 時(shí)間:2007-05-23 來(lái)源:網(wǎng)絡(luò) 收藏
作 者: 莊榮城

不知道在什幺時(shí)候, 出現(xiàn)了 module 這種東西,的確,它是 的一大革新。有了 module 之后,寫(xiě) device driver 不再是一項(xiàng)惡夢(mèng),修改 kernel 也不再是一件痛苦的事了。因?yàn)槟悴恍枰看我獪y(cè)試 driver 就重新 compile kernel 一次。那簡(jiǎn)直是會(huì)累死人。Module 可以允許我們動(dòng)態(tài)的改變 kernel,加載 device driver,而且它也能縮短我們 driver development 的時(shí)間。在這篇文章里,我將要跟各位介紹一下 module 的原理,以及如何寫(xiě)一個(gè) module。

module 翻譯成中文就是,不過(guò),事實(shí)上去翻譯這個(gè)字一點(diǎn)都沒(méi)意義。在講之前,我先舉一個(gè)例子。相信很多人都用過(guò) RedHat。在 RedHat 里,我們可以執(zhí)行 sndconfig,它可以幫我們 config 聲卡。config 完之后如果捉得到你的聲卡,那你的聲卡馬上就可以動(dòng)了,而且還不用重新激活計(jì)算機(jī)。這是怎幺做的呢 ? 就是靠module。module 其實(shí)是一般的程序。但是它可以被動(dòng)態(tài)載到 kernel 里成為 kernel的一部分。載到 kernel 里的 module 它具有跟 kernel 一樣的權(quán)力。可以 access 任何 kernel 的 data structure。你聽(tīng)過(guò) kdebug 嗎 ? 它是用來(lái) debug kernel 的。它就是先將它本身的一個(gè) module 載到 kernel 里,而在 user space 的 gdb 就可以經(jīng)由跟這個(gè) module 溝通,得知 kernel 里的 data structure 的值,除此之外,還可以經(jīng)由載到 kernel 的 module 去更改 kernel 里 data structure。

我們知道,在寫(xiě) C 程序的時(shí)候,一個(gè)程序只能有一個(gè) main。Kernel 本身其實(shí)也是一個(gè)程序,它本身也有個(gè) main,叫 start_kernel()。當(dāng)我們把一個(gè) module 載到 kernel 里的時(shí)候,它會(huì)跟 kernel 整合在一起,成為 kernel 的一部分。請(qǐng)各位想想,那 module 可以有 main 嗎 ? 答案很明顯的,是 No。理由很簡(jiǎn)單。一個(gè)程序只能有一個(gè) main。在使用 module 時(shí),有一點(diǎn)要記住的是 module 是處于被動(dòng)的角色。它是提供某些功能讓別人去使用的。

Kernel 里有一個(gè)變量叫 module_list,每當(dāng) user 將一個(gè) module 載到 kernel 里的時(shí)候,這個(gè) module 就會(huì)被記錄在 module_list 里面。當(dāng) kernel 要使用到這個(gè) module 提供的 function 時(shí),它就會(huì)去 search 這個(gè) list,找到 module,然后再使用其提供的 function 或 variable。每一個(gè) module 都可以 export 一些 function 或變量來(lái)讓別人使用。除此之外,module 也可以使用已經(jīng)載到 kernel 里的 module 提供的 function。這種情形叫做 module stack。比方說(shuō),module A 用到 module B 的東西,那在加載 module A 之前必須要先加載 module B。否則 module A 會(huì)無(wú)法加載。除了 module 會(huì) export 東西之外,kernel 本身也會(huì) export 一些 function 或 variable。同樣的,module 也可以使用 kernel 所 export 出來(lái)的東西。由于大家平時(shí)都是撰寫(xiě) user space 的程序,所以,當(dāng)突然去寫(xiě) module 的時(shí)候,會(huì)把平時(shí)寫(xiě)程序用的 function 拿到 module 里使用。像是 printf 之類(lèi)的東西。我要告訴各位的是,module 所使用的 function 或 variable,要嘛就是自己寫(xiě)在 module 里,要嘛就是別的 module 提供的,再不就是 kernel 所提供的。你不能使用一般 libc 或 glibc所提供的 function。像 printf 之類(lèi)的東西。這一點(diǎn)可能是各位要多小心的地方。(也許你可以先 link 好,再載到 kernel,我好象試過(guò),但是忘了)

剛才我們說(shuō)到 kernel 本身會(huì) export 出一些 function 或 variable 來(lái)讓 module 使用,但是,我們不是萬(wàn)能的,我們?cè)蹒壑?kernel 有開(kāi)放那里東西讓我們使用呢 ? 提供一個(gè) command,叫 ksyms,你只要執(zhí)行 ksyms -a 就可以知道 kernel 或目前載到 kernel 里的 module 提供了那些 function 或 variable。底下是我的系統(tǒng)的情形:

c0216ba0 drive_info_R744aa133
c01e4a44 boot_cpu_data_R660bd466
c01e4ac0 EISA_bus_R7413793a
c01e4ac4 MCA_bus_Rf48a2c4c
c010cc34 __verify_write_R203afbeb
. . . . .

在 kernel 里,有一個(gè) symbol table 是用來(lái)記錄 export 出去的 function 或 variable。除此之外,也會(huì)記錄著那個(gè) module export 那些 function。上面幾行中,表示 kernel 提供了 drive_info 這個(gè) function/variable。所以,我們可以在 kernel 里直接使用它,等載到 kernel 里時(shí),會(huì)自動(dòng)做好 link 的動(dòng)作。由此,我們可以知道,module 本身其實(shí)是還沒(méi)做 link 的一些 object code。一切都要等到 module 被加載 kernel 之后,link 才會(huì)完成。各位應(yīng)該可以看到 drive_info 后面還接著一些奇怪的字符串。_R744aa133,這個(gè)字符串是根據(jù)目前 kernel 的版本再做些 encode 得出來(lái)的結(jié)果。為什幺額外需要這一個(gè)字符串呢 ?

Linux 不知道從那個(gè)版本以來(lái),就多了一個(gè) config 的選項(xiàng),叫做 Set version number in symbols of module。這是為了避免對(duì)系統(tǒng)造成不穩(wěn)定。我們知道 Linux 的 kernel 更新的很快。在 kernel 更新的過(guò)程,有時(shí)為了效率起見(jiàn),會(huì)對(duì)某些舊有的 data structure 或 function 做些改變,而且一變可能有的 variable 被拿掉,有的 function 的 prototype 跟原來(lái)的都不太一樣。如果這種情形發(fā)生的時(shí)候,那可能以前 2.0.33 版本的 module 拿到 2.2.1 版本的 kernel 使用,假設(shè)原來(lái) module 使用了 2.0.33 kernel 提供的變量叫 A,但是到了 2.2.1 由于某些原因必須把 A 都設(shè)成 NULL。那當(dāng)此 module 用在 2.2.1 kernel 上時(shí),如果它沒(méi)去檢查 A 的值就直接使用的話(huà),就會(huì)造成系統(tǒng)的錯(cuò)誤。也許不會(huì)整個(gè)系統(tǒng)都死掉,但是這個(gè) module 肯定是很難發(fā)揮它的功能。為了這個(gè)原因,Linux 就在 compile module 時(shí),把 kernel 版本的號(hào)碼 encode 到各個(gè) exported function 和 variable 里。

所以,剛才也許我們不應(yīng)該講 kernel 提供了 drive_info,而應(yīng)該說(shuō) kernel 提供了 driver_info_R744aa133 來(lái)讓我們使用。這樣也許各位會(huì)比較明白。也就是說(shuō),kernel 認(rèn)為它提供的 driver_info_R744aa133 這個(gè)東西,而不是 driver_info。所以,我們可以發(fā)現(xiàn)有的人在加載 module 時(shí),系統(tǒng)都一直告訴你某個(gè) function 無(wú)法 resolved。這就是因?yàn)?kernel 里沒(méi)有你要的 function,要不然就是你的 module 里使用的 function 跟 kernel encode 的結(jié)果不一樣。所以無(wú)法 resolve。解決方式,要嘛就是將 kernel 里的 set version 選項(xiàng)關(guān)掉,要嘛就是將 module compile 成 kernel 有辦法接受的型式。

那有人就會(huì)想說(shuō),如果 kernel 認(rèn)定它提供的 function 名字叫做 driver_info_R744aa133 的話(huà),那我們寫(xiě)程序時(shí),是不是用到這個(gè) funnction 的地方都改成 driver_info_R744aa133 就可以了。答案是 Yes。但是,如果每個(gè) function 都要你這樣寫(xiě),你不會(huì)覺(jué)得很煩嗎 ? 比方說(shuō),我們?cè)趯?xiě) driver 時(shí),很多人都會(huì)用到 printk 這個(gè) function。這是 kernel 所提供的 function。它的功能跟 printf 很像。用法也幾乎都一樣。是 debug 時(shí)很好用的東西。如果我們 module 里用了一百次 printk,那是不是我們也要打一百次的 printk_Rdd132261 呢 ? 當(dāng)然不是,聰明的人馬上會(huì)想到用 #define printk printk_Rdd132261 就好了嘛。所以啰,Linux 很體貼的幫我們做了這件事。

如果各位的系統(tǒng)有將 set version 的選項(xiàng)打開(kāi)的話(huà),那大家可以到 /usr/src/linux/include/linux/modules 這個(gè)目錄底下。這個(gè)目錄底下有所多的 ..ver檔案。這些檔案其實(shí)就是用來(lái)做 #define 用的。我們來(lái)看看 ksyms.ver 這個(gè)檔案里,里面有一行是這樣子的 :

#define printk _set_ver(printk)

set_ver 是一個(gè) macro,就是用來(lái)在 printk 后面加上 version number 的。有興趣的朋友可以自行去觀(guān)看這個(gè) macro 的寫(xiě)法。用了這些 ver 檔,我們就可以在 module 里直接使用 printk 這樣的名字了。而這些 ver 檔會(huì)自動(dòng)幫我們做好 #define 的動(dòng)作??墒?,我們可以發(fā)現(xiàn)這個(gè)目錄有很多很多的 ver 檔。有時(shí)候,我們?cè)蹒壑牢覀円艚械?function 是在那個(gè) ver 檔里有定義呢 ? Linux 又幫我們做了一件事。/usr/src/linux/include/linux/modversions.h 這個(gè)檔案已經(jīng)將全部的 ver 檔都加進(jìn)來(lái)了。所以在我們的 module 里只要 include 這個(gè)檔,那名字的問(wèn)題都解決了。但是,在此,我們奉勸各位一件事,不要將 modversions.h 這個(gè)檔在 module 里 include 進(jìn)來(lái),如果真的要,那也要加上以下數(shù)行:

#ifdef MODVERSIONS
#include linux/modversions.h>;
#endif

加入這三行的原因是,避免這個(gè) module 在沒(méi)有設(shè)定 kernel version 的系統(tǒng)上,將 modversions.h 這個(gè)檔案 include 進(jìn)來(lái)。各位可以去試試看,當(dāng)你把 set version 的選項(xiàng)關(guān)掉時(shí),modversions.h 和 modules 這個(gè)目錄都會(huì)不見(jiàn)。如果沒(méi)有上面三行,那 compile 就不會(huì)過(guò)關(guān)。所以一般來(lái)講,modversions.h 我們會(huì)選擇在 compile 時(shí)傳給 gcc 使用。就像下面這個(gè)樣子。

gcc -c -D__KERNEL__ -DMODULE -DMODVERSIONS main.c
-include usr/src/linux/include/linux/modversions.h

在這個(gè) command line 里,我們看到了 -D__KERNEL__,這是說(shuō)要定義 __KERNEL__ 這個(gè) constant。很多跟 kernel 有關(guān)的 header file,都必須要定義這個(gè) constant 才能 include 的。所以建議你最好將它定義起來(lái)。另外還有一個(gè) -DMODVERSIONS。這個(gè) constant 我剛才忘了講。剛才我們說(shuō)要解決 fucntion 或 variable 名字 encode 的方式就是要 include modversions.h,其實(shí)除此之外,你還必須定義 MODVERSIONS 這個(gè) constant。再來(lái)就是 MODULE 這個(gè) constant。其實(shí),只要是你要寫(xiě) module 就一定要定義這個(gè)變量。而且你還要 include module.h 這個(gè)檔案,因?yàn)?_set_ver 就是定義在這里的。

講到這里,相信各位應(yīng)該對(duì) module 有一些認(rèn)識(shí)了,以后遇到 module unresolved 應(yīng)該不會(huì)感到困惑了,應(yīng)該也有辦法解決了。

剛才講的都是使用別人的 function 上遇到的名字 encode 問(wèn)題。但是,如果我們自己的 module 想要 export 一些東西讓別的 module 使用呢。很簡(jiǎn)單。在 default 上,在你的 module 里所有的 global variable 和 function 都會(huì)被認(rèn)定為你要 export 出去的。所以,如果你的 module 里有 10 個(gè) global variable,經(jīng)由 ksyms,你可以發(fā)現(xiàn)這十個(gè) variable 都會(huì)被 export 出去。這當(dāng)然是個(gè)很方便的事啦,但是,你知道,有時(shí)候我們根本不想把所有的 variable 都 export 出去,萬(wàn)一有個(gè) module 沒(méi)事亂改我們的 variable 怎幺辦呢 ? 所以,在很多時(shí)候,我們都只會(huì)限定幾個(gè)必要的東西 export 出去。在 2.2.1 之前的 kernel (不是很確定) 可以利用 register_symtab 來(lái)幫我們。但是,現(xiàn)在更新的版本早就出來(lái)了。所以,在此,我會(huì)介紹 kernel 2.2.1 里所提供的。kernel 2.2.1 里提供了一個(gè) macro,叫做 EXPORT_SYMBOL,這是用來(lái)幫我們選擇要 export 的 variable 或 function。比方說(shuō),我要 export 一個(gè)叫 full 的 variable,那我只要在 module 里寫(xiě):

EXPORT_SYMBOL(full);

就會(huì)自動(dòng)將 full export 出去,你馬上就可以從 ksyms 里發(fā)現(xiàn)有 full 這個(gè)變量被 export 出去。在使用 EXPORT_SYMBOL 之前,要小心一件事,就是必須在 gcc 里定義 EXPORT_SYMTAB 這個(gè) constant,否則在 compile 時(shí)會(huì)發(fā)生 parser error。所以,要使用 EXPORT_SYMBOL 的話(huà),那 gcc 應(yīng)該要下:

gcc -c -D__KERNEL__ -DMODULE -DMODVERSIONS -DEXPORT_SYMTAB
main.c -include /usr/src/linux/include/linux/modversions.h

如果我們不想 export 任何的東西,那我們只要在 module 里下

EXPORT_NO_SYMBOLS;

就可以了。使用 EXPORT_NO_SYMBOLS 用不著定義任何的 constant。其實(shí),如果各位使用過(guò)舊版的 register_symbol 的話(huà),一定會(huì)覺(jué)得新版的方式比較好用。至少我是這樣覺(jué)得啦。因?yàn)槭褂?register_symbol 還要先定義出自己的 symbol_table,感覺(jué)有點(diǎn)麻煩。

當(dāng)我們使用 EXPORT_SYMBOL 把一些 function 或 variable export 出來(lái)之后,我們使用 ksyma -a 去看一些結(jié)果。我們發(fā)現(xiàn) EXPORT_SYMBOL(full) 的確是把 full export出來(lái)了 :

c8822200 full [my_module]
c01b8e08 pci_find_slot_R454463b5
. . .

但是,結(jié)果怎幺跟我們想象中的不太一樣,照理說(shuō),應(yīng)該是 full_Rxxxxxx 之類(lèi)的東西才對(duì)啊,怎幺才出現(xiàn) full 而已呢 ? 奇怪,問(wèn)題在那里呢 ?

其實(shí),問(wèn)題就在于我們沒(méi)有對(duì)本身的 module 所 export 出來(lái)的 function 或 variable 的名字做 encode。想想,如果在 module 的開(kāi)頭。我們加入一行

#define full full_Rxxxxxx

之后,我們?cè)僦匦?compile module 一次,載到 kernel 之后,就可以發(fā)現(xiàn) ksyms -a 顯示的是

c8822200 full_Rxxxxxx [my_module]
c01b8e08 pci_find_slot_R454463b5
. . . . .

了。那是不是說(shuō),我們要去對(duì)每一個(gè) export 出來(lái)的 variable 和 function 做 define 的動(dòng)作呢 ? 當(dāng)然不是啰。記得嗎,前頭我們講去使用 kernel export 的 function 時(shí),由于 include 了一些 .ver 的檔案,以致于我們不用再做 define 的動(dòng)作?,F(xiàn)在,我們也要利用 .ver 的檔案來(lái)幫我們,使我們 module export 出來(lái)的 function 也可以自動(dòng)加入 kernel version 的 information。也就是變成 full_Rxxxxxx 之類(lèi)的東西。

Linux 里提供了一個(gè) command,叫 genksyms,就是用來(lái)幫我們產(chǎn)生這種 .ver 的檔案的。它會(huì)從 stdin 里讀取 source code,然后檢查 source code 里是否有 export 的 variable 或 function。如果有,它就會(huì)自動(dòng)為每個(gè) export 出來(lái)的東西產(chǎn)生一些 define。這些 define 就是我們之前說(shuō)的。等我們有了這些 define 之后,只要在我們的 module 里加入這些 define,那 export 出來(lái)的 function 或 variable 就會(huì)變成上面那個(gè)樣子。

假設(shè)我們的程序都放在一個(gè)叫 main.c 的檔案里,我們可以使用下列的方式產(chǎn)生這些 define。

gcc -E -D__GENKSYMS__ main.c | genksyms -k 2.2.1 >; main.ver

gcc 的 -E 參數(shù)是指將 preprocessing 的結(jié)果 show 出來(lái)。也就是說(shuō)將它 include 的檔案,一些 define 的結(jié)果都展開(kāi)。-D__GENKSYMS__ 是一定要的。如果沒(méi)有定義這個(gè) constant,你將不會(huì)看到任何的結(jié)果。用一個(gè)管線(xiàn)是因?yàn)?genksyms 是從 stdin 讀資料的,所以,經(jīng)由管線(xiàn)將 gcc 的結(jié)果傳給 genksyms。-k 2.2.1 是指目前使用的 kernel 版本是 2.2.1,如果你的 kernel 版本不一樣,必須指定你的 kernel 的版本。產(chǎn)生的 define 將會(huì)被放到 main.ver 里。產(chǎn)生完 main.ver 檔之后,在 main.c 里將它 include 進(jìn)來(lái),那一切就 OK 了。有件事要告訴各位的是,使用這個(gè)方式產(chǎn)生的 module,其 export 出來(lái)的東西會(huì)經(jīng)由 main.ver 的 define 改頭換面。所以如果你要讓別人使用,那你必須將 main.ver 公開(kāi),不然,別人就沒(méi)辦法使用你 export 出來(lái)的東西了。

講了這幺多,相信各位應(yīng)該都已經(jīng)比較清楚 module 在 kernel 中是怎幺樣一回事,也應(yīng)該知道為什幺有時(shí)候 module 會(huì)無(wú)法加載了。除此之外,各位應(yīng)該還知道如何使自己 module export 出來(lái)的東西也具有 kernel version 的 information。

接下來(lái),要跟各位講的就是,如何寫(xiě)一個(gè) module 了。其實(shí),寫(xiě)一個(gè) module 很簡(jiǎn)單的。如果你了解我上面所說(shuō)的東西。那我再講一次,再用個(gè)例子,相信大家就都會(huì)了。要寫(xiě)一個(gè) module,必須要提供兩個(gè) function。這兩個(gè) function 是給 insmod 和 rmmod 使用的。它們分別是 init_module(),以及 cleanup_module()。

int init_module();
void cleanup_module();

相信大家都知道在 Linux 里可以使用 insmod 這個(gè) command 來(lái)將某個(gè) module 加載。比方說(shuō),我有一個(gè) module 叫 hello.o,那使用 insmod hello.o 就可以將 hello 這個(gè) module 載到 kernel 里。觀(guān)察 /etc/modules 應(yīng)該就可以看到 hello 這個(gè) module 的名字。如果要將 hello 這個(gè) module 移除,則只要使用 rmmod hello 就可以了。insmod 在加載 module 之后,就會(huì)去呼叫 module 所提供的 init_module()。如果傳回 0 表示成功,那 module 就會(huì)被加載。如果失敗,那加載的動(dòng)作就會(huì)失敗。一般來(lái)講,我們?cè)?init_module() 做的事都是一些初始化的工作。比方說(shuō),你的 module 需要一塊內(nèi)存,那你就可以在 init_module() 做 kmalloc 的動(dòng)作。想當(dāng)然爾。cleanup_module() 就是在 module 要移除的時(shí)候做的事。做的事一般來(lái)講就是一些善后的工作,比方像把之前 kmalloc 的內(nèi)存 free 掉。

由于 module 是載到 kernel 使用的,所以,可能別的 module 會(huì)使用你的 module,甚至某些 process 也會(huì)使用到你的 module,為了避免 module 還有人使用時(shí)就被移除,每個(gè) module 都有一個(gè) use count。用來(lái)記錄目前有多少個(gè) process 或 module 正在使用這個(gè) module。當(dāng) module 的 use count 不等于 0 時(shí),module 是不會(huì)被移除掉的。也就是說(shuō),當(dāng) module 的 use count 不等于 0 時(shí),cleanup_module() 是不會(huì)被呼叫的。

在此,我要介紹三個(gè) macro,是跟 module 的 use count 有關(guān)的。

MOD_INC_USE_COUNT
MOD_DEC_USE_COUNT
MOD_IN_USE

MOD_INC_USE_COUNT 是用來(lái)增加 module 的 use count,而 MOD_DEC_USE_COUNT 是用來(lái)減少 module 的 use count。至于 MOD_IN_USE 則是用來(lái)檢查目前這個(gè) module 是不是被使用中。也就是檢查 use count 是否為 0。module 的 use count 必須由寫(xiě) module 的人自己來(lái) maintain。系統(tǒng)并不會(huì)自動(dòng)為你把 use count 加一或減一。一切都得由自己控制。下面有一個(gè)例子,但是,并不會(huì)介紹這三個(gè) macro 的使用方法。將來(lái)如果有機(jī)會(huì),我再來(lái)介紹這三個(gè) macro 的用法。

這個(gè)例子很簡(jiǎn)單。其實(shí)只是示范如何使用 init_module() 以及 cleanup_module() 來(lái)寫(xiě)一個(gè) module。當(dāng)然,這兩個(gè) function 只是構(gòu)成 module 的基本條件罷了。至于 module 里要提供的功能則是看各人的需要。

main.c
#define MODULE
#include linux/module.h>;
#include asm/uaccess.h>;
int full;
EXPORT_SYMBOL(full); /* 將 full export 出去 */
int init_module( void )
{
printk( 5>; Module is loadedn );
return 0;
}
void cleanup_module( void )
{
printk( 5>; Module is unloadedn );
}

關(guān)于 printk 是這樣子的,它是 kernel 所提供的一個(gè)打印訊息的 function。kernel 有 export 這個(gè) function。所以你可以自由的使用它。它的用法跟 printf 幾乎一模一樣。唯獨(dú)訊息的開(kāi)頭是 5>;,其實(shí),不見(jiàn)得這三個(gè)字符啦。也可以是 4>;,3>;,7>; 等等的東西。這是代表這個(gè)訊息的 prioirty 或 level。5>; 表示的是跟 KERNEL 有關(guān)的訊息。

main.ver:

利用 genksyms 產(chǎn)生出來(lái)的。

gcc -E -D__GENKSYMS__ main.c | genksyms -k 2.2.1 >; main.ver

接下來(lái),就是要把 main.c compile 成 main.o

gcc -D__KERNEL__ -DMODVERSIONS -DEXPORT_SYMTAB -c
-I/usr/src/linux/include/linux -include
/usr/src/linux/include/linux/modversions.h
-include ./main.ver main.c

好了。main.o 已經(jīng)成功的 compile 出來(lái)了,現(xiàn)在下一個(gè) command,

insmod main.o

檢查看 /proc/modules 里是否有 main 這個(gè) module。如果有,表示 main 這個(gè) module 已經(jīng)載到 kernel 了。再下一個(gè)指令,看看 full export 出去的結(jié)果。

ksyms

結(jié)果顯示

Address Symbol Defined by
c40220e0 full_R355b84b2 [main]
c401d04c ne_probe [ne]
c401a04c ei_open [8390]
c401a094 ei_close [8390]
c401a504 ei_interrupt [8390]
c401af1c ethdev_init [8390]
c401af80 NS8390_init [8390]

可以看到 full_R355b84b2,表示,我們已經(jīng)成功的將 full 的名字加上 kernel version 的 information 了。當(dāng)我們不需要這個(gè) module 時(shí),我們就可以下一個(gè) command,

rmmod main

這樣 main 就會(huì)被移除掉了。再檢查看看 /proc/modules 就可以發(fā)現(xiàn) main 那一行不見(jiàn)了。各位現(xiàn)在可以看一下 /var/log/message 這個(gè)檔案,應(yīng)該可以發(fā)現(xiàn)以?xún)尚?

Apr 12 14:19:05 host kernel: Module is loaded
Apr 12 14:39:29 host kernel: Module is unloaded

這兩行就是 printk 印出來(lái)的。

關(guān)于 module 的介紹已經(jīng)到此告一段落了。其實(shí),使用 module 實(shí)在是很簡(jiǎn)單的一件事。對(duì)于要發(fā)展 driver 或是增加 kernel 某些新功能的人來(lái)講,用 module 不啻為一個(gè)方便的方式。希望這篇文章對(duì)各位能有所幫助。


莊榮城 (J.C. Chuang), cjc86@cs.ccu.edu.tw
linux操作系統(tǒng)文章專(zhuān)題:linux操作系統(tǒng)詳解(linux不再難懂)


關(guān)鍵詞: 模塊 Linux 內(nèi)核編譯

評(píng)論


相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉