Modules
  一、什麽是 Modules
  Modules 的字面意思就是模塊,在此指的是 kernel Modules;簡單來說,一個模塊提供了一個功能,如 isofs、minix、nfs、lp 等等。傳統來講,模塊化有兩個方法解决。設計者可以把各項功能分離到單獨的叫做綫程的處理中去,或者是將內核
  以包含/排除一些功能的方式重新編譯。如果把功能分離到綫程中去,那麽內核就叫做“微內核”(micro-kernel),這種解决方法增加了綫程間協調工作的通信開銷。就象名字暗示的那樣,這種解决方案的優點在於內核的大小。
  Linux的解决方案是包含內核模塊,這些模塊是可以按需要隨時裝入和卸下的。這樣做可以使得內核的大小和通信量都達到最小。將模塊從內核中獨立出來,不必預先『綁』在 kernel codes 中。這樣做有三種優點: 第一, 將來修改 kernel 時,不必全部重新 compile,可節省不少時間;第二, 若需要安裝新的 Modules ,不
  必重新 compile kernel,衹要插入 (通過insmode指令) 對應的 Modules 即可;第三,減少內核對係統資源的占用,內核可以集中精力做最基本的事情,把一些擴展功能都交由Modules實現。
  模塊也可以用來嘗試新的內核代碼而不需要每次都創建和重激活內核。但是,這樣做帶來的問題是:使用內核模塊通常會輕微的增加性能和內存開支。一個可加載模塊肯定會産生更多的代碼,這種代碼和額外的數據結構會占用更多一點的內存。另外因為間接訪問內核資源也讓模塊的效率輕微降低。
  模塊化的思想已經被廣泛接受,主要的原因在於它可以擴展係統的功能,用戶可以靈活的配置係統。Apache也采取了這種功能擴展方式,在本文中主要討論是內核的模塊安裝與卸載,Apache模塊的安裝請參照Apapce的相關文檔。
  二、如何加載模塊?
  加載內核模塊的方法有兩種。第一種使用insmod命令手工把它插入到內核。另一個更智能的方法是在需要的時候加載這個模塊︰這叫做按需加載(demand loading)。當內核發現需要一個模塊的時候,例如當用戶安裝一個不在內核的文件係統的時候,內核會請求內核守護進程(kerneld)試圖加載合適的模塊。
  說到這裏就不能不提到內核守護進程kerneld了,它非常的聰明,能夠主動的把您需要的 Modules 自動插入 kernel,將沒用到的 module 從kernel中清退。Kerneld由兩個獨立的部分構成:一部分工作於Linux的內核,負責嚮daemon發送請求;另一部分工作於係統的用戶數據區,負責調入由內核請求指定的Modules。若少了這個
  kerneld,就衹能通過手工的方式,用insmode或modeprobe命令進行加載。
  三、Modules的相關命令介紹
  與Modules有關的命令有:
  lsmode :列出已經被內核調入的模塊
  insmode:將某個module插入到內核中
  rmmod:將某個module從內核中卸載
  depmod: 生成依賴文件,告訴將來的 insmod 要從哪兒調入 Modules。這個依賴 文件就在/lib/Modules/[您的kernel版本]/Modules.dep。
  Kerneld:負責自動的將模塊調入內核和把模塊從內核中卸載。
  四、編譯一個最小的Linux內核
  模塊一般用來支持那些不經常使用的功能。例如,通常情況下你僅使用撥號網絡,因此網絡功能並不是任何時候都需要的,那麽就應該使用可裝入的模塊來提供這個功能。僅在你進行撥號聯接的時候,該模塊纔被裝入。而在你斷掉連接的時候它會被自動卸下。這樣會使內核使用內存的量最小,減小係統的負荷。
  當然,那些象硬盤訪問這樣時時刻刻都需要的功能,則必須作在內核裏。如果你搭一臺網絡工作站或web服務器,那麽網絡功能是時刻都需要的,你就應該考慮把網絡功能編譯到內核裏。另外一個方法是在啓動的時候就裝入網絡模塊。這種方法的優點是你不需要重新編譯內核。而缺點是網絡功能不能特別高效。
  按照以上的原則,我們首先列出一張清單,看看 kernel 中哪些選項是非有不可的,也就是說,這些東西是必須被編譯到內核中的。將那些非必需的模塊剔除到內核以外。
  第一個是root所在的硬盤配置。哪果您的硬盤是IDE接口,就把 ide 的選項標記下來。如果是SCSI接口,請把您的接口參數及 SCSI id 記標下來。
  第二個是選擇使用哪一個文件係統。Linux的默認文件係統是是 ext2 ,那麽就一定要把它標記下來。如果機器中還其它的操作係統,如win98或windows NT,您還會可能選擇FAT32或NTFS的支持,不過後面你可以通過手工加載的方式來加入新的模塊支持。
  第三個是選擇Linux所支持的可執行文件格式。這裏有兩種格式可供選擇:
  elf:這是當前Linux普遍支持的可執行文件格式,必須編譯到內核中 。
  a.out: 這是舊版的Linux的可執行文件各函數庫的格式,如果你確認肯定用不到這種格式的可執行文件,那麽就可以不把它編譯到內核當中。
  以上這些內容,是必須要編譯到內核中的。其它的內容凡是所有選項中m提示的,都選擇m,這樣可以通過手工的方式添加該模塊。
  ** Loadable module support*Enable loadable module support (CONFIG_Modules) [Y/n/?]Set version
  information on all symbols for Modules (CONFIG_MODVERSIONS) [N/y/?]Kernel daemon support (e.g.
  autoload of Modules) (CONFIG_KERNELD) [Y/n/?]
  分別回答 Y,N,Y 。其中 CONFIG_KERNELD 的 default 值是 N, 所以要註意選擇Y。
  make config 完後,仍舊是 make dep; make clean。
  接下來要 make zlilo 或 make zImage。
  然後 make Modules ; make Modules_install 。完成之後,就編譯出一個沒有調入多餘模塊的一個“幹淨的”內核映像文件了。
  五、如何手工加載Modules
  如果要以手工的方式加載模塊, 建議最好使用 modprobe, 因為它可以解决模塊之間的依賴性問題,以聲卡的部分來說,以sound blaster 為例其總共有以下模塊:
  sb 33652 0 (autoclean)
  uart401 6160 0 (autoclean) [sb]
  sound 56492 0 (autoclean) [sb uart401]
  soundcore 2372 5 (autoclean) [sb sound]
  這些模塊都要加載上來,整個聲卡才能工作,而且它們之間是有依賴性關係的。最核心的 soundcore必須首先裝入, 最後裝入sb。但一般人是不知道其先後順序的。因此, modprobe 就是用來解决這個問題用的。
  通常我們衹要
  modprobe sb
  它就會自動的找出 sb 用到的所有的模塊, 將它們一一 的加載進來,故一般使用者就不用去傷腦筋了。
  那麽內核是怎麽知道這些模塊間的依賴性關係的呢?原來,在係統啓動腳本裏有一條'depmod -a'命令,會給係統中的所有可用的模塊創建一個依賴關係的列表。而 'modprobe module-name'會使用這個列表,在裝入指定的
  模塊前先裝入那些事先裝入的模塊。如果在這個從屬列表中找不到'module-name'的話,它會給出相應的出錯信息。
  但若使用 insmod, 它可不會自動完成其它模塊的調入。比如說,我們要加入PPP模塊,用這個命令:
  root/root>insmod ppp
  root/root>
  如果操作成功,係統出現操作提示符。如果沒有成功,可能出現下列信息:
  /lib/Modules/2.2.10/net/ppp.o: unresolved symbol slhc_init_Rsmp_1ca65fca
  /lib/Modules/2.2.10/net/ppp.o: unresolved symbol slhc_compress_Rsmp_cfd3a418
  /lib/Modules/2.2.10/net/ppp.o: unresolved symbol slhc_free_Rsmp_b99033d9
  /lib/Modules/2.2.10/net/ppp.o: unresolved symbol slhc_toss_Rsmp_a152cec0
  /lib/Modules/2.2.10/net/ppp.o: unresolved symbol slhc_remember_Rsmp_07972313
  /lib/Modules/2.2.10/net/ppp.o: unresolved symbol slhc_uncompress_Rsmp_3bb36b01
  [root /root]#
  這說明,PPP模塊沒有加載成功,錯誤提示中的unresolved symbol說明,PPP模塊所需要的一些模塊還沒有載入。錯誤提示第一行的內容是:slhc_init_Rsmp_1ca65fca ,這是哪個模塊?這其中可能需要一些經驗來做判斷,它是以slhc開頭的,就試試slhc吧。
  root/root>insmod slhc 一切正常,然後我們再加載PPP模塊
  root/root>insmod ppp
  root/root>
  這回沒有什麽返回信息,說明PPP模塊加載成功了。
  六、從內存中卸載一個Modules.
  要卸載一個模塊,首先用lsmod看看該模塊是否確實已經加載上來,然後再做操作。除此之外,在碰到有依賴關係的模塊時,從內核中卸載模塊的過程與載入的過程恰好相反,它遵循“first in last out“的準則,即在一係列有依賴關係的模塊中,必須先卸載最後加載進來的模塊,最後卸載最先加載進來的模塊。比如:如果要用 rmmod 移除正在使用中的模塊(如上例,要卸載slhc, 但仍有PPP模塊在使用它)會出現錯誤提示:Device or resource busy 。所以,在將PPP模塊從內存中卸載後,纔可能將slhc模塊從內存中卸載。
  總之,在卸載模塊時,對於可能出現的模塊間依賴性問題,Linux會給你提示足夠的信息,仔細查看這些信息,是能夠為你采取相應的操作並最終解决問題提供幫助的。