熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

Linux Kernel核心中文手冊 (12)

2013-11-13 16:20:15  來源: Oracle 

  Modules
  
  本章描述 Linux 核心如何只在需要的時候才動態加載函數例如文件系統
  
  Linux 是一個完整的核心就是說它是一個單一的巨大的程序核心的功能組件可以訪問它的所有的內部數據結構以及例程另一種方法是使用一個微內核的結構核心的功能片被分成獨立的單元互相之間有嚴格的通訊機制這樣通過配置進程向核心增加新的組件不花多少時間比如你希望增加一個 NCR SCSI 卡的 SCSI 驅動程序你不需要把它連接到核心否則你不得不配置並建立一個新的核心才能使用這個 NCR 作為一種變通 Linux 允許在你需要的時候動態地加載和卸載操作系統的組件 Linux 的模塊是可以在系統啟動之後任何時候動態連接到核心的代碼塊它們可以在不被需要的時候從核心刪除並卸載大多數 Linux 核心模塊是設備驅動程序偽設備驅動程序比如網絡驅動程序或文件系統
  
  你可以使用 insmod 和 rmmod 命令明確地加載和卸載 Linux 核心模塊或者在需要這些模塊的時候由核心自己要求核心守護進程( kerneld )加載和卸載這些模塊在需要的時候動態地加載代碼相當有吸引力因為它讓核心可以保持最小而且核心非常靈活我當前的 Intel 核心大量使用模塊它只有 K 大小我通常只適用 VFAT 文件系統所以我建立我的 Linux 核心當我安裝一個 VFAT 分區的時候自動加載 VFAT 文件系統當我卸載 VFAT 文件系統的時候系統探測到我不再需要 VFAT 文件系統模塊把它從系統中刪除模塊也可以用來嘗試新的核心代碼而不需要每次都創建和重啟動核心但是沒有這麼好的事情使用核心模塊通常伴隨輕微的性能和內存開支一個可加載模塊必須提供更多的代碼這種代碼和額外的數據結構會占用更多一點的內存另外因為間接訪問核心資源也讓模塊的效率輕微降低
  
  一旦 Linux 核心加載它就和普通核心代碼一樣成為核心的一部分它和任何核心代碼擁有相同的權利和義務換句話說 Linux 核心模塊和所有的核心代碼或設備驅動程序一樣可能讓核心崩潰
  
  既然模塊在需要的時候可以使用核心資源它們必須能夠找到這些資源比如一個模塊需要調用 kmalloc() 核心內存分配例程當建立的時候( build )模塊不知道內存中 kmalloc() 在哪裡所以當這個模塊加載的時候在模塊能夠工作之前核心必須整理模塊對於 kmmalloc() 的所有的引用核心在核心符號表中保存了所有核心資源的列表所以當模塊加載的時候它可以解析模塊中對於這些資源的引用 Linux 允許模塊堆棧(堆砌)就是一個模塊需要另一個模塊的服務例如 VFAT 文件系統模塊需要 FAT 文件系統模塊的服務因為 VFAT 文件系統或多或少是 FAT 文件系統上的擴展一個模塊需要另一個模塊的服務或資源的情況和一個模塊需要核心自己的服務和資源的情況非常相似只不過這時請求的服務在另一個此前已經加載的模塊鐘當每一個模塊加載的時候核心修改它的符號表把這個新加載的模塊的所有輸出的資源或符號加到核心符號表中這意味著當下一個模塊加載的時候它可以訪問已經加載的模塊的服務
  
  當時圖卸載一個模塊的時候核心需要知道這個模塊不在用它還需要一些方法來通知它准備卸載的模塊用這種方法模塊可以在它從核心刪除之前釋放它占用的任何的系統資源例如核心內存或中斷當模塊卸載的時候核心把這個模塊輸出到核心符號表中所有的符號都刪除
  
  除了寫的不好的可加載模塊可能破壞操作系統之外還有另一個危險如果你加載一個為比你當前運行的核心要早或遲的核心建立的模塊會發生什麼?如果這個模塊執行一個核心例程而提供了錯誤的參數就會引起問題核心可以選擇防止這種情況當模塊加載的時候進行嚴格的版本檢查
  
   Loading a Module (加載一個模塊)
  
  用兩種方法可以加載一個核心模塊第一種使用 insmod 命令手工把它插入到核心第二種更聰明的方法是在需要的時候加載這個模塊這叫做按需加載( demand loading )當核心發現需要一個模塊的時候例如當用戶安裝一個不在核心的文件系統的時候核心會請求核心守護進程( kerneld )試圖加載合適的模塊
  
  Kerneld 和 insmod lsmod 以及 rmmod 都在 modules 程序包中
  
  核心守護進程通常是擁有超級用戶特權的一個普通的用戶進程當它啟動的時候(通常是在系統啟動的時候啟動)它打開一個通向核心的 IPC 通道核心使用這個連接向 kerneld 發送消息請求它執行大量的任務 Kerneld 的主要功能是加載和卸載核心模塊但是它也可以執行其它任務比如需要的時候在串行線上啟動 PPP 連接不需要的時候把它關閉 Kerneld 本身並不執行這些任務它運行必要的程序比如 insmod 來完成工作 Kerneld 只是核心的一個代理調度它的工作
  
  參見 include/linux/kerneldh
  
  insmod 命令必須找到它要加載的被請求的核心模塊按徐加載的核心模塊通常放在 /lib/mmodules/kernelversion 目錄裡邊核心模塊和系統中的其它程序一樣是連接程序的目標文件但是它們被連接成可以重定位的映像就是沒有連接到特定地址去運行的映像它們可以是 aout 或 elf 格式的目標文件 Insmod 指向一個特權的系統調用找出系統的輸出符號它們以符號名稱和值(例如它的地址)的形式成對存放核心的輸出符號表放在核心維護的模塊列表中的第一個 module 數據結構用 module_list 指針指向只有在核心編譯和連接的時候特殊指定的符號才加到這個表中而並非核心的每一個符號都輸出它的模塊例如符號 request_irq 是一個系統例程當一個驅動程序希望控制一個特定的系統中斷的時候必須調用它在我當前的核心上它的值是 xcd 你可以檢查文件 /proc/ksyms 或使用 ksyms 工具簡單地查看輸出的核心符號和它們的值 Ksyms 工具可以向你顯示所有的輸出的核心符號或者只顯示哪些加載模塊輸出的符號 Insmod 把模塊讀取到它的虛擬內存使用核心的輸出符號來整理這個模塊對於核心例程和資源的未解析的引用這個整理過程是用向內存中的模塊映像打補丁的方式進行 insmod 物理上把符號的地址寫到模塊的合適的位置
  
  參見 kernel/modulec kernel_syms() include/linux/moduleh
  
  
  當 insmod 整理完了模塊對於輸出的核心符號的引用之後他向核心請求足夠的空間放置新的核心又是通過特權的系統調用核心分配一個新的 module 數據結構和足夠的核心內存來存放這個新的模塊並把它放置到核心的模塊列表的最後這個新的模塊被標記為 UNINITIALIZED 顯示了核心模塊列表的後面兩個模塊 FAT 和 VFAT 被加載到了內存圖中沒有顯示的有列表的第一個模塊這是一個偽模塊用於放置核心的輸出符號表你可以使用命令 lsmod 列出所有加載的核心模塊和它們之間的依賴關系 Lsmod 只是簡單地把從核心 module 數據結構列表中提取的 /proc/modules 重新安排了格式核心為模塊分配的內存映射到 insmod 進程的地址空間所以它可以訪問它 Insmod 把模塊拷貝到分配的空間並把它重定位這樣它就可以從被分配的核心地址運行必須進行重定位因為一個模塊不能期待在兩次被加載到相同的地址或者在兩個不同的 Linux 系統上被加載到相同的地址這一次重定位又關系到要用適當的地址為模塊的映像打補丁
  
  參見 kernel/modulec create_module()
  
  新的模塊也向核心輸出符號 Insmod 建立一個輸出映像表每一個核心模塊必須包含模塊初始化和模塊清除的歷程這些符號必須是專用的而不是輸出的但是 insmod 必須知道它們的地址能把它們傳遞給核心所有這些做好之後 Insmod 現在准備初始化這個模塊它執行一個特權的系統調用把這個模塊的初始化和清除例程的地址傳遞給核心
  
  參見 kernel/modulec sys_init_module()
  
  當一個新的模塊加到核心的時候它必須更新核心的符號表並改變被新的模塊使用的模塊其它模塊依賴的模塊必須在它們的符號表之後維護一個引用列表用它們的 module 數據結構指向 顯示了 VFAT 文件系統模塊依賴於 FAT 文件系統模塊所以 FAT 模塊包含一個到 VFAT 模塊的引用這個引用在 VFAT 模塊加載的時候增加核心調用模塊的初始化例程如果成功它開始安裝這個模塊模塊的清除例程的地址保存在它的 module 數據結構中當這個模塊卸載的時候核心會去調用最後模塊的狀態被設置為 RUNNING
  
   Unloading a Module
  
  模塊可以使用 rmmod 命令刪除但是 kerneld 可以把所有不用的按需加載的模塊從系統中刪除每一次它的空閒計時器到期的時候 kerneld 執行系統調用請求從系統刪除所有的不需要的按需加載的模塊這個計時器的值由你在啟動 kerneld 的時候設定我的 kerneld 每 秒檢查一次如果你安裝了一個 iso CD ROM 而你的 iso 文件系統是一個可加載模塊那麼在 CD ROM 卸載不久 iso 模塊會從核心中刪除
  
  如果核心中的其它組件依賴於一個模塊它就不能被刪除例如如果你安裝了一個或更多的 VFAT 文件系統你就不能卸載 VFAT 模塊如果你檢查 ls 輸出你會看到每一個模塊關聯一個計數器例如
  
  Module: #pages: Used by:
  
  msdos
  
  vfat (autoclean)
  
  fat [vfat msdos] (autoclean)
  
  這個計數器( count )是依賴於這個模塊的核心實體的數目在上例中 vfat 和 msdos 都依賴於 fat 模塊所以 fat 模塊的計數器是 Vfat 和 msdos 模塊的依賴數
From:http://tw.wingwit.com/Article/program/Oracle/201311/18169.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.