Linux 核心(kernel)及核心模組的主要功能,若用比較白話的說法是『驅動各式各樣的硬體設備』與『支援各種功能的軟體使用』,上述兩項功能再加上眾多 Distribution 廠商的推動,成功地將 Linux 應用在各式各樣商業化的場合,應用範圍之廣,大到超級電腦叢集運算、中的有伺服器以及桌上型電腦、小至嵌入式系統,四處都有 Linux 的蹤影,這就是 Linux 為何能夠只花短短的十多年,就在電腦業界產生這麼巨大的影響力。
本文從介紹 Linux 與 Linux 核心模組基本概念開始,進而提及與核心模組相關的六個指令,以及其擺放模組檔案的相關目錄,最後介紹更新核心的注意事項。
Linux 開機的時候,通常經由 Boot Loader(GRUB 或是 LILO)載入 Linux kernel,Linux kernel 通常位於 /boot/ 底下名為 vmlinuz 開頭的檔案,在核心載入之後,『最基本的、每台主機都用到的硬體與軟體功能』就一體成形地由核心來驅動提供這些功能;至於其他『選用的、每台主機不一定用到的功能』,則交給核心模組來視需要的時候才做載入動作。
下圖為核心載入時候的訊息,開機完成後記載在 /var/log/dmesg 檔案內以供查閱。

先前說到『最基本的、每台主機都用到的功能』由核心本身來驅動,對於一台標準 PC、載入一個很普通的核心來說,不外乎是:
*驅動 CPU 運算(包括支援多核心 CPU)
*記憶體管理
*行程(Process)管理
*提供行程呼叫 system calls 達到基本 I/O 功能
*IDE 介面驅動以及抓到這個介面上的設備,像是硬碟與光碟機
*支援 ext2 檔案系統(這樣才有檔案系統樹狀目錄架構,接續使用檔案系統內的其他程式)
*基本 I/O 埠(像是 PS/2 鍵盤)
*驅動 PCI/AGP/PCI-E 介面並發現其上的設備,例如:驅動顯示卡最基本的文字模式功能
*Sockets 功能與 TCP/IP 網路等等…
為了保持執行效率以及避免核心提供過多不必要的功能導致核心變得肥大,其餘『選用的、每台主機不一定用到的功能』在編譯 Linux 核心的時候,通常選擇將此功能作成 Loadable Kernel Module(可載入的核心模組),觀察已經載入哪些模組,則是使用指令「lsmod」如下圖。

許多的硬體介面卡以及晶片組,都是建議採用模組的方式來載入,不要編譯進 Linux 核心內,畢竟不是每台主機都有提供那些硬體設備;至於軟體功能也是類似硬體的處理方式,如果此功能不見得一定要包含在核心的話,或是不一定每台主機都用的到,就把這個軟體功能作成核心模組等到要使用的時候再載入即可。
硬體的模組像是各類型的介面卡與晶片組,例如:網路卡、顯示卡、音效卡、SATA 晶片、USB、1394、印表埠、SCSI 或 SAS(序列 SCSI)或是 RAID 介面卡(或是晶片)等等。
軟體的模組像是支持各類型的檔案系統(ext3、nfs、vfat…)、IPv4/IPv6 進階功能及防火牆相關的功能模組、軟體模擬的 RAID(Software RAID)與 LVM(用到 device-mapper 功能)等等。
接下來就以測試機的網路卡模組 pcnet32 為例,介紹兩、三個常用模組以及與核心模組有關的指令。
與核心模組相關的主要有六個指令,分別是:
*列出(list)已經載入模組的「lsmod」
*觀察模組資訊(information)的「modinfo」
*用來卸除(remove)已經載入模組的「rmmod」
*用來載入(insert)模組的「insmod」
*提供自動探測(probe)相依性(dependence)來載入或卸除模組的「modprobe」
*做出模組相依的資料檔案『modules.dep』的「depmod」
稍加注意不難發現,這六個指令都有『mod』這個關鍵字(也就是模組的英文『module』)
首先介紹是用來列出(list)已經載入的核心模組「lsmod」指令,依照第一行欄位標示,某個模組可能會被其他模組使用(Used by)也就是模組之間是有可能相依的(dependence)。

舉例來說:筆者的測試主機,軟體的部份有 ext3 需要基層 jbd 模組;硬體的部份則是網路卡驅動程式 pcnet32 需要基礎 mii 模組(如下圖精簡後的內容)。


這麼多的模組名稱,怎知道各個模組的用途呢?我們可以利用「modinfo」指令來觀察模組資訊(information)。
就以 pcnet32 模組為例,在指令「modinfo pcnet32」輸出內容有一堆資料,先觀察『描述』(description)得知這是網路卡的驅動程式(Driver)。

除此之外,由圖中『檔名』(filename)得知實際 pcnet32 模組檔是位於 /lib/modules/2.6.18-53.el5/kernel/drivers/net/pcnet32.ko,這個 net/ 目錄也存放其他廠牌型號的網路卡驅動程式。
下圖是列出此目錄的檔案列表,看來 Linux 內建就支援相當多種類的網路卡,若以最平價也是最知名的『螃蟹卡』來舉例(由 8139too 模組來驅動),使用「modinfo 8139too」可觀察其詳細資訊。

使用指令 rmmod 可以卸載模組,以測試機來說,將 pcnet32 模組卸載(請注意卸載後網路就會不通了喔!)是使用「rmmod pcnet32」指令。

例如要把剛剛卸載的 pcnet32 模組載入回去,則是使用「insmod /lib/modules/2.6.18-53.el5/kernel/drivers/net/pcnet32.ko」(請注意模組檔案需使用完整的檔案名稱,不能只輸入 pcnet32)

承接先前 rmmod 與 insmod 範例,若是想要先卸除底層 mii 模組,則是會出現『ERROR: Module mii is in use by pcnet32』錯誤訊息,因為 mii 模組被 pcnet32 使用(相依),需先卸除 pcnet32 才能卸除基礎的 mii 模組;相反地當要載入這兩個模組的時候,若是尚未載入基礎的 mii 就載入 pcnet32 則是會得到『error inserting ...: -1 Unknown symbol in module』錯誤訊息,這時基礎的 mii 模組需要先載入,才可以載入 pcnet32 成功。(載入 mii 需先查出他放在哪裡,再用 insmod 載入)

先前介紹的模組相依性,對於使用 rmmod 與 insmod 指令來操作時,實際上會造成一些阻礙與麻煩,想要方便一點的話,可使用「modprobe」指令來替代,尤其是載入模組的時候會特別方便。
在下圖中,卸載模組使用「modprobe -r mii」、「modprobe -r pcnet32」雖然沒有幫上大忙,但載入的時候使用「modprobe pcnet32」則自動將相依的 mii 模組一起載入,而且不用輸入完整檔案路徑名稱,使用起來相當的方便。

先前提到 modprobe 指令會依照相依性載入相關模組,他是如何知道模組之間的相依性呢?以測試主機來說 modprobe 指令是讀取 /lib/modules/2.6.18-53.el5/modules.dep 檔案內容來判斷的,至於這個檔案則是使用「depmod -a」指令製作出來的。

所以若是模組數量有增減或相依性有異動,強烈建議再次執行「depmod -a」指令重新產出『modules.dep』檔案(請觀察檔案最後一次修改的時間來判斷此檔是否被更新),這樣不只是 modprobe 指令可以用簡短的名稱載入或卸載模組(卸載模組時搭配 -r 選項),modinfo 指令也可以用簡短的名稱查詢資訊(例如:「modinfo pcnet32」);若沒有 modules.dep 檔案的話,使用 modinfo 指令則是要像 insmod 一樣,輸入完整的模組檔案路徑名稱才行(例如:「modinfo /lib/modules/2.6.18-53.el5/kernel/drivers/net/pcnet32.ko」)。

先前提過核心模組實際存放的位置是在 /lib/modules/ 目錄下,這裡要注意到的是她以核心版本號碼區分目錄存放;預設通常只有安裝一組核心與核心模組,所以也就只有一個目錄名稱,以測試機來說是『2.6.18-53.el5/』這個目錄名稱,這個目錄名稱會與核心版本號碼相同,我們可以使用指令「uname -r」觀察正在使用的核心版本號碼,以 RHEL5.1 來說:
「uname -r」指令輸出為『2.6.18-53.el5』
所以與這個版本的相關檔案則是放在 /lib/modules/2.6.18-53.el5/ 目錄下
像是『modules.dep』相依性關聯檔、『kernel/drivers/』底下各種類型的硬體驅動程式等等。

一般來說 Linux 主機跑的好好地,沒必要也不會去更新 Linux 核心,那就列舉一些可能更新核心的原因如下:
*新的核心有新的功能(我們剛好要用到),且舊的卻剛好沒有此功能
*舊的核心有發生不安全或是不穩定的現象,希望藉由更新核心來改善
例如:新的核心支援新的硬體設備,像是新的網路卡、或是支援新的軟體功能等等。
更新核心的時候,最好保留舊的核心,原因如下:
*新的核心若無法開機,舊的核心又被移除的話,會陷入無法開機的困境。
*新的核心上線跑了一陣子,卻沒有比使用舊的核心來的『狀況好』,還可以再換回來用舊的。
以測試機為例,在 RHEL5.1 系統拿 RHEL5.2 的核心更新,使用指令「rpm -ivh kernel-2.6.18-92.el5.i686.rpm」來安裝新的核心(同時也保留舊的),避免使用 -U(升級)或是 -F(修正)的 rpm 指令選項(會將舊的核心移除喔!請小心使用),安裝完成新的核心以後,順道觀察在 /boot/ 目錄底下會有兩個 vmlinuz 開頭的 Linux 核心檔案,以及 /lib/modules/ 內會各自有各自的目錄。

最後記得要編輯 /boot/grub/menu.lst 檔案有關 default 參數那一行,如果 default=0 代表使用第一個 title 的核心開機(以下圖來說是新的核心開機);如果 default=1 是使用第二個 title 的核心開機。
