什麼是內核模塊?
當一個操作系統發展進化到一定階段的時候,設計者們往往要面對一種進退兩難的局面。如果把對所有功能的支持都放到操作系統內核裡,那麼控制系統的核心程序--系統內核就會變的非常大而且笨拙。如果把其中一些功能不包含在內核之內,那麼這些功能在運行的時候就會非常慢,甚至根本不能運行。操作系統的設計人員解決這種兩難局面的典型方法是把這些去留兩可的功能模塊化。
傳統來講,模塊化有兩個方法解決。設計者可以把各項功能分離到單獨的叫做線程的處理中去,或者是將內核以包含/排除一些功能的方式重新編譯。如果把功能分離到線程中去,那麼內核就叫做“微內核”(micro-kernel)這種解決方法增加了線程間為協調工作而通訊的開銷。就象名字暗示的那樣,這種解決方案的優點在於內核的大小。Linux的解決方案是包含內核模塊,這些模塊是可以按需要隨時裝入和卸下的。這樣做可以使得內核的大小和通訊量都達到最小。
模塊支持的發展
自從我開始使用linux,這個系統裡就一直有內核模塊。隨著Linux的發展,模塊的數量、支持機制和對它們的操作也一直在發展。
最初,是使用modprobe/depmod和insmod/lsmod/rmmod/ksyms來管理這些模塊。這些工具在一些手冊(man page)中有所描述。在Linux 1.3中,加入了一個叫kerneld的守護程序,它可以自動管理內核模塊。kerneld mini-HOWTO(FTP://metalab.unc.edu/pub/Linux/docs/HOWTO/)中對它有詳細的介紹。
什麼時候應該使用模塊?
模塊一般用來支持那些僅於部分時間運行的功能。例如,通常情況下你僅使用撥號網絡,因此網絡功能並不是任何時候都需要的,那麼就應該使用可裝入的模塊來提供這個功能。
僅當你撥通ISP的時候,該模塊才被裝入。而在你斷掉連接的時候它會被自動卸下。這樣會使內核使用內存的量最小,而且可以加速操作。
當然,那些象硬盤存取這樣時時刻刻都需要的功能,則必須作在內核裡。如果你搭一台網絡工作站或web服務器,那麼網絡功能是時刻都需要的,你就應該考慮把網絡功能編譯到內核裡。另外一個方法是在啟動的時候就裝入網絡模塊。這種方法的優點是你不需要重新編譯內核。而缺點是網絡功能不能特別高效。
如何重新編譯內核
linux比其他商業操作系統的一個主要優點是它的源代碼是完全開放的。你可以重新編譯或修改系統的任何一部分。然而這個優點是在假設你是一個計算機程序員的前提下的。你需要了解象make和C語言這樣的一些知識。如果你僅是一個計算機最終用戶,那麼試著重新編譯內核可能是很痛苦的。此外,如果你在編譯的過程中犯了錯誤,你可能不得不整個重新安裝。就我本人而論,只有在所有的其他可能的解決方案都不行的情況下才會考慮重新編譯內核。
然而,就象有人說,重新編譯是非常簡單的。linux的文檔Kernel-HOWTO (ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/)裡給出了重新編譯的詳細介紹。如果你懶得看這個說明,那麼大體的步驟是這樣:先把解包,tar -zxvf linux-2.x.xx.tar.gz,源代碼缺省的路徑是在/usr/src/linux目錄裡。然後確認一下/usr/include/asm,/usr/include/linux和/usr/include/scsi目錄是否正確的連接在源代碼的目錄裡:
cd /usr/include
rm -rf asm linux scsi
ln -s /usr/src/linux/include/asm-i386 asm
ln -s /usr/src/linux/include/linux linux
ln -s /usr/src/linux/include/scsi scsi確認一下沒有以前留下來的舊的.o文件:
cd /usr/src/linux
make mrproper配置內核,make config或者用帶菜單的make menUConfig或Xwindow下的make xconfig來做這一步,把你所需要的功能包括進內核裡,然後用make dep來設置所有的依賴關系都是正確的,下面用make zImage來編譯一個壓縮的內核映像,如果你裝了lilo的話還要make zlilo一下來通知Lilo使用新內核來引導系統。如果你在前面make config的時候把某些功能作成模塊的話,還需要make modules,然後在make modules_install。最後重新啟動就可以了。
如何在啟動的時候裝入內核模塊
要在啟動的時候裝入模塊,必須把裝入命令包括進適當的啟動腳本裡。Linux系統的啟動腳本並不包括在任何官方發布的linux包中,每種linux發布,象Red Hat、Slackware、Debian等都有他們自己的啟動腳本。因此不可能給出每種系統的更詳細的介紹。讀者應該自己查找一下你用的linux發布的腳本文件是哪個。首先你應該看看有沒有叫'rc*.d'的目錄或文件,這裡星號的意思是這個位置可能是任何字符,通常啟動腳本都是叫這個名字的。然後使用grep命令看找找'depmod -a'和'insmod'。linux的模塊安裝文檔Modules Installation mini-HOWTO (ftp://metalab.unc.edu/pub/Linux/docs/linux-doc-project/)裡有更詳細的說明。
我必須提醒你注意,在更改這些啟動腳本的之前最好先保存一下備份。這樣萬一你出錯了,可以回到原來的狀態。
Linux模塊安裝mini-HOWTO文檔中推薦,如果你使用RedHat或Debian,最好創建一個叫'/etc/rc.d/init.d/modules.init'的文件來包含這些裝入命令。然而我的RedHat版本在'/etc/rc.d/rc.sysinit'文件裡有'depmod -a'命令,你可能會找到至少一行包含modprobe或insmod命令。把那些你想在啟動的時候就裝入的模塊寫在這個文檔中。
重新啟動計算機以後,使用lsmod命令來檢查模塊是否已經被激活運行了。
按需自動裝入模塊
自從1.3.57版本的linux內核以後,系統中就加入了一個叫做'kerneld'的守護進程(daemon),這個程序的工作是在需要的時候自動裝入模塊,而在不需要的時候自動卸下它。這樣做的好處是僅僅需要發行內核版本的一個發布。這個daemon會按需要自動裝入特定系統的特定功能模塊。如果你的系統的啟動腳本裡包含'/sbin/kerneld'這樣的一行,那你的系統裡就被設置為使用這個程序。
很棒的是你所需要的所有模塊都可以在不要任何額外設置的情況下正確運行。如果你需要改變設置,kerneld mini-HOWTO文檔中詳細描述了這些配置文件和應該如何修改它。
如何從腳本程序中裝入模塊
有時你需要人為地控制一個模塊什麼時候被裝入。那麼首先你需要修改一下配置文件,以確認該模塊不會被kerneld自動的裝入。然後在寫一個腳本來啟動和終止這個功能模塊。
在系統啟動腳本裡的'depmod -a'命令會給系統中的所有可用的模塊創建一個從屬關系的列表。這個很必要,因為某些模塊是假設其他一些模塊已經被裝入的。命令:'modprobe module-name'會使用這個從屬列表,以使得在裝入指定的模塊前先裝入那些事先裝入的模塊。如果在這個從屬列表中找不到'module-name'的話,它會給出一個出錯信息。如果所有依賴的其他模塊都已經被裝入了,那麼可以使用insmod命令來裝入它。
舉個例子,比如說要使用撥號網絡。可能有幾個腳本是用來啟動撥號網絡的。你需要把modprobe或insmod命令加到這個腳本裡去,來裝入網絡功能模塊。我推薦使用lsmod和grep來檢查一下該模塊是否已經被裝入了。你還需要在終止撥號網絡的的腳本裡加一行rmmod命令來卸下網絡功能模塊。關於撥號網絡腳本的細節,請看PPP mini-HOWTO (ftp://metalab.unc.edu/pub/Linux/docs/linux-doc-project/)。
更多資料
我收集的很多關於模塊的資料都是來自linux文檔工程LDP。這裡是該工程的主頁http://metalab.unc.edu/mdw/ldp.Html。
Linux文檔工程(LDP)是專門開發關於linux系統的好的可靠的文檔資源的。LDP的目標是收集和整理各種在線文檔,包括手冊man page,html等,內容覆蓋linux的安裝、使用和運行等。
該工程所有已整理好的文檔都可以在這裡找到ftp://sunsite.unc.edu/pub/Linux/docs/。我使用的幾本手冊是The Linux Users' Guide, The Linux Kernel HOWTO, The Linux Modules Installation mini- HOWTO和The kerneld mini- HOWTO.帶有最好的除錯信息的文檔是Linux PCMCIA HOWTO,另外還有些資料來自Linux PPP HOWTO和Linux IPX HOWTO。
另外一個非常好的信息來源是Deja-News的linux的新聞組文檔。這是一個把所有在linux新聞組貼過的有用的信息都收集下來的文檔庫。它支持全文搜索,也允許你貼新的問題上去。由於這個站的資料太多,因此找你需要的信息的時候要有耐心和恆心。堅持,你要找的東西通常就藏在裡面。