可載入核心模組(LKM)
/ L-K-M /
核心原則上可以把每一個驅動程式與功能都永久編進一個巨大的程式裡——但那樣一來,支援一個新裝置就意味著重建整個核心並重新開機,而每台機器都得背負它根本沒有的硬體的程式碼。可載入核心模組(loadable kernel module)是另一種選擇:一段核心程式碼,能按需插入正在執行的核心、也能從中移除。想像一把可換頭的電動工具:工具本體(核心本身)保持不動,你只需喀一聲裝上此刻需要的鑽頭或起子頭,用完再拔出來。
具體來說,一個模組被單獨編譯成一個檔案(在 Linux 上是 .ko 檔)。當你載入它時(例如用 modprobe 或 insmod),核心在執行期把模組的程式碼與資料連結進自己的位址空間、執行模組的初始化函式以登記它所提供的東西(一個新的裝置驅動、一種檔案系統類型、一個網路協定),自此模組便以完整的核心特權執行,彷彿它一直都是核心的一部分。當不再需要它時,核心執行模組的結束函式並把它解除連結、釋放記憶體。驅動程式是最常見的模組:插上一個 USB 裝置,核心便能自動載入相符的驅動模組。
它之所以重要,是因為模組讓一個單核心擁有近似更模組化設計的彈性,又不必放棄在單一特權位址空間中執行的速度——你只發行一個小核心,並只載入每台機器所需的東西。關鍵且誠實的警告是其安全與穩定的代價:模組以完整核心特權在核心自己的位址空間中執行,因此一個有錯誤或惡意的模組可能當掉或攻陷整個系統。這正是為什麼正式環境的核心往往要求模組必須先經過密碼學簽署才肯載入。
你插上一個 Wi-Fi 隨身天線。核心比對它的裝置 ID、執行 modprobe 載入正確的驅動模組(比方說 iwlwifi.ko),模組的初始化登記了這個網路裝置,於是天線就以一個可用的介面出現——不必重開機、不必重建核心。執行 lsmod,你就能看到目前所有已載入的模組以及彼此的相依關係。
按需把驅動程式碼插入正在執行的核心;不再需要時再移除它。
模組並沒有被沙盒隔離:它在核心空間以完整特權執行、共享核心的位址空間。這與微核心的使用者空間驅動程式恰恰相反,後者以一個被隔離的行程執行——模組較快,但單一錯誤就能拖垮整台機器。