/proc
文件系統(tǒng)是一個虛擬文件系統(tǒng),通過它可以使用一種新的方法在 Linux? 內(nèi)核空間和用戶空間之間進(jìn)行通信。在 /proc
文件系統(tǒng)中,我們可以將對虛擬文件的讀寫作為與內(nèi)核中實體進(jìn)行通信的一種手段,但是與普通文件不同的是,這些虛擬文件的內(nèi)容都是動態(tài)創(chuàng)建的。本文對
/proc 虛擬文件系統(tǒng)進(jìn)行了介紹,并展示了它的用法。
最初開發(fā) /proc 文件系統(tǒng)是為了提供有關(guān)系統(tǒng)中進(jìn)程的信息。但是由于這個文件系統(tǒng)非常有用,因此內(nèi)核中的很多元素也開始使用它來報告信息,或啟用動態(tài)運行時配置。 /proc 文件系統(tǒng)包含了一些目錄(用作組織信息的方式)和虛擬文件。虛擬文件可以向用戶呈現(xiàn)內(nèi)核中的一些信息,也可以用作一種從用戶空間向內(nèi)核發(fā)送信息的手段。實際上我們并不會同時需要實現(xiàn)這兩點,但是本文將向您展示如何配置這個文件系統(tǒng)進(jìn)行輸入和輸出。 盡管像本文這樣短小的一篇文章無法詳細(xì)介紹 /proc 的所有用法,但是它依然對這兩種用法進(jìn)行了展示,從而可以讓我們體會一下 /proc 是多么強(qiáng)大。清單 1 是對 /proc 中部分元素進(jìn)行一次交互查詢的結(jié)果。它顯示的是 /proc 文件系統(tǒng)的根目錄中的內(nèi)容。注意,在左邊是一系列數(shù)字編號的文件。每個實際上都是一個目錄,表示系統(tǒng)中的一個進(jìn)程。由于在 GNU/Linux 中創(chuàng)建的第一個進(jìn)程是 init 進(jìn)程,因此它的 process-id 為 1.然后對這個目錄執(zhí)行一個 ls 命令,這會顯示很多文件。每個文件都提供了有關(guān)這個特殊進(jìn)程的詳細(xì)信息。例如,要查看 init 的 command-line 項的內(nèi)容,只需對 cmdline 文件執(zhí)行 cat 命令。 /proc 中另外一些有趣的文件有:cpuinfo,它標(biāo)識了處理器的類型和速度;pci,顯示在 PCI 總線上找到的設(shè)備;modules,標(biāo)識了當(dāng)前加載到內(nèi)核中的模塊。 清單 1. 對 /proc 的交互過程
清單 2 展示了對 /proc 中的一個虛擬文件進(jìn)行讀寫的過程。這個例子首先檢查內(nèi)核的 TCP/IP 棧中的 IP 轉(zhuǎn)發(fā)的目前設(shè)置,然后再啟用這種功能。 清單 2. 對 /proc 進(jìn)行讀寫(配置內(nèi)核)
另外,我們還可以使用 sysctl 來配置這些內(nèi)核條目。有關(guān)這個問題的更多信息,請參閱 參考資料 一節(jié)的內(nèi)容。 順便說一下,/proc 文件系統(tǒng)并不是 GNU/Linux 系統(tǒng)中的惟一一個虛擬文件系統(tǒng)。在這種系統(tǒng)上,sysfs 是一個與 /proc 類似的文件系統(tǒng),但是它的組織更好(從 /proc 中學(xué)習(xí)了很多教訓(xùn))。不過 /proc 已經(jīng)確立了自己的地位,因此即使 sysfs 與 /proc 相比有一些優(yōu)點,/proc 也依然會存在。還有一個 debugfs 文件系統(tǒng),不過(顧名思義)它提供的更多是調(diào)試接口。debugfs 的一個優(yōu)點是它將一個值導(dǎo)出給用戶空間非常簡單(實際上這不過是一個調(diào)用而已)。 內(nèi)核模塊簡介 可加載內(nèi)核模塊(LKM)是用來展示 /proc 文件系統(tǒng)的一種簡單方法,這是因為這是一種用來動態(tài)地向 Linux 內(nèi)核添加或刪除代碼的新方法。LKM 也是 Linux 內(nèi)核中為設(shè)備驅(qū)動程序和文件系統(tǒng)使用的一種流行機(jī)制。 如果您曾經(jīng)重新編譯過 Linux 內(nèi)核,就可能會發(fā)現(xiàn)在內(nèi)核的配置過程中,有很多設(shè)備驅(qū)動程序和其他內(nèi)核元素都被編譯成了模塊。如果一個驅(qū)動程序被直接編譯到了內(nèi)核中,那么即使這個驅(qū)動程 序沒有運行,它的代碼和靜態(tài)數(shù)據(jù)也會占據(jù)一部分空間。但是如果這個驅(qū)動程序被編譯成一個模塊,就只有在需要內(nèi)存并將其加載到內(nèi)核時才會真正占用內(nèi)存空間。 有趣的是,對于 LKM 來說,我們不會注意到有什么性能方面的差異,因此這對于創(chuàng)建一個適應(yīng)于自己環(huán)境的內(nèi)核來說是一種功能強(qiáng)大的手段,這樣可以根據(jù)可用硬件和連接的設(shè)備來加載 對應(yīng)的模塊。 下面是一個簡單的 LKM,可以幫助您理解它與在 Linux 內(nèi)核中看到的標(biāo)準(zhǔn)(非動態(tài)可加載的)代碼之間的區(qū)別。清單 3 給出了一個最簡單的 LKM.(可以從本文的 下載 一節(jié)中下載這個代碼)。 清單 3 包括了必須的模塊頭(它定義了模塊的 API、類型和宏)。然后使用 MODULE_LICENSE 定義了這個模塊使用的許可證。此處,我們定義的是 GPL,從而防止會污染到內(nèi)核。 清單 3 然后又定義了這個模塊的 init 和 cleanup 函數(shù)。my_module_init 函數(shù)是在加載這個模塊時被調(diào)用的,它用來進(jìn)行一些初始化方面的工作。my_module_cleanup 函數(shù)是在卸載這個模塊時被調(diào)用的,它用來釋放內(nèi)存并清除這個模塊的蹤跡。注意此處 printk 的用法:這是內(nèi)核的 printf 函數(shù)。KERN_INFO 符號是一個字符串,可以用來對進(jìn)入內(nèi)核回環(huán)緩沖區(qū)的信息進(jìn)行過濾(非常類似于 syslog)。 最后,清單 3 使用 module_init 和 module_exit 宏聲明了入口函數(shù)和出口函數(shù)。這樣我們就可以按照自己的意愿來對這個模塊的 init 和 cleanup 函數(shù)進(jìn)行命名了,不過我們最終要告訴內(nèi)核維護(hù)函數(shù)就是這些函數(shù)。 清單 3. 一個簡單的但可以正常工作的 LKM(simple-lkm.c)
清單 3 盡管非常簡單,但它卻是一個真正的 LKM?,F(xiàn)在讓我們對其進(jìn)行編譯并在一個 2.6 版本的內(nèi)核上進(jìn)行測試。2.6 版本的內(nèi)核為內(nèi)核模塊的編譯引入了一種新方法,我發(fā)現(xiàn)這種方法比原來的方法簡單了很多。對于文件 simple-lkm.c,我們可以創(chuàng)建一個 makefile,其惟一內(nèi)容如下:
要編譯 LKM,請使用 make 命令,如清單 4 所示。 |
|