郭松,謝維波
(華僑大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院,福建泉州362021)
L inux下Proc文件系統(tǒng)的編程剖析
郭松,謝維波
(華僑大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院,福建泉州362021)
論述Linux下可加載內(nèi)核模塊和虛擬文件系統(tǒng)的運(yùn)作原理,比較內(nèi)核程序運(yùn)行在微內(nèi)核和一體化內(nèi)核兩種組織方式下的優(yōu)缺點(diǎn).在此基礎(chǔ)上,提出Proc文件系統(tǒng)下的編程,包括編寫內(nèi)核模塊和Proc文件系統(tǒng)程序的一些過程,并對(duì)主要代碼進(jìn)行解析說明.通過一個(gè)編程示例,給出Proc文件系統(tǒng)編程的框架,以顯示Linux虛擬文件系統(tǒng)的能力.
Proc文件系統(tǒng);Linux;內(nèi)核模塊;虛擬文件系統(tǒng)
通過對(duì)Proc文件系統(tǒng)中文件的讀寫操作,達(dá)到對(duì)驅(qū)動(dòng)程序或其他內(nèi)核程序的控制,實(shí)現(xiàn)用戶態(tài)程序與核心態(tài)程序的數(shù)據(jù)通信.向Proc寫入信息,可以使用標(biāo)準(zhǔn)的文件系統(tǒng)提供的機(jī)制.文件系統(tǒng)注冊(cè)的標(biāo)準(zhǔn)機(jī)制,是每個(gè)文件系統(tǒng)都用自己的函數(shù)來處理索引節(jié)點(diǎn)和文件操作.通過編寫內(nèi)核模塊來實(shí)現(xiàn)用戶態(tài)到核心態(tài)通信,通過內(nèi)核模塊在Proc文件系統(tǒng)中創(chuàng)建文件夾或文件,來為用戶程序提供接口.基于此,本文介紹編寫內(nèi)核模塊和Proc文件系統(tǒng)程序的一些過程,并對(duì)主要代碼進(jìn)行解析說明.
1.1 可加載內(nèi)核模塊
為了支持構(gòu)建安全操作系統(tǒng),現(xiàn)代中央處理器(CPU)一般提供至少兩種運(yùn)行模式:特權(quán)模式與用戶模式.它們不僅具有不同的優(yōu)先權(quán)等級(jí),還有各自的地址空間,即內(nèi)核空間和用戶空間.所有的現(xiàn)代CPU都具有保護(hù)系統(tǒng)軟件不受應(yīng)用程序破壞的功能,即在CPU中實(shí)現(xiàn)不同的操作模式或級(jí)別[1].
Unix系統(tǒng)使用最高級(jí)別和最低級(jí)別——內(nèi)核程序運(yùn)行在特權(quán)模式,在這個(gè)級(jí)別中可以進(jìn)行所有的操作;而應(yīng)用程序運(yùn)行在用戶模式,處理器控制著對(duì)硬件的直接訪問,以及對(duì)內(nèi)存的非授權(quán)訪問.
根據(jù)各個(gè)管理模塊是否放在特權(quán)模式下,操作系統(tǒng)有微內(nèi)核和一體化內(nèi)核兩種組織方式[1],如圖1所示.傳統(tǒng)的Unix及大部分類Unix操作系統(tǒng)基本上都屬于一體化內(nèi)核組織方式,而M ach,Window s N T,Window 2000/XP等基本屬于微內(nèi)核組織方式(圖1).
圖1 操作系統(tǒng)內(nèi)核組織方式Fig.1 O rganization of operating system kernel
一體化內(nèi)核組織方式的優(yōu)點(diǎn)是效率高、安全,但其缺點(diǎn)是不容易擴(kuò)展.若要增加一種新設(shè)備驅(qū)動(dòng)或文件系統(tǒng)等功能,則必須對(duì)內(nèi)核重新編譯定制,而且占用內(nèi)存較多.微內(nèi)核組織方式的優(yōu)點(diǎn)是可擴(kuò)展性好,占用內(nèi)存少,但缺點(diǎn)是效率低,也沒有一體化內(nèi)核安全[1].
在Linux中引入內(nèi)核模塊機(jī)制,主要目的是為了充分吸取兩者的優(yōu)點(diǎn),克服它們的缺點(diǎn).內(nèi)核模塊是Linux用來高效地利用微內(nèi)核的理論優(yōu)點(diǎn)而不會(huì)降低系統(tǒng)性能的一種方法.
Linux內(nèi)核模塊本質(zhì)上是存放在文件系統(tǒng)中的ELF對(duì)象文件,沒有鏈接,不能獨(dú)立運(yùn)行,但可以動(dòng)態(tài)加載(Insmod)到內(nèi)核并與內(nèi)核鏈接,從而成為內(nèi)核的一部分,或者從內(nèi)核解除鏈接.其基本機(jī)理是, Linux內(nèi)核本身有一張內(nèi)核符號(hào)表(Kernel Sym bol Table),包括用來描述系統(tǒng)提供哪些函數(shù)服務(wù)、系統(tǒng)全局變量及它們的地址.在Linux用一個(gè)宏EXPORT_SYMBOL(或EXPORT_SYMBOL_GPL,定義在include/linux/module.h中)導(dǎo)出需要輸出的函數(shù)及系統(tǒng)全局變量,以使內(nèi)核各個(gè)模塊能夠互相引用.同理,每個(gè)內(nèi)核目標(biāo)模塊也有一張類似的符號(hào)表,其中定義了此模塊所提供的功能函數(shù)及變量,以及此模塊可能要用到的系統(tǒng)內(nèi)核,或者其他已加載模塊中的函數(shù)及變量,但此時(shí)又不知其實(shí)際地址.
為了使內(nèi)核模塊真正成為L(zhǎng)inux系統(tǒng)內(nèi)核的一部分,必須將此內(nèi)核模塊動(dòng)態(tài)裝入到內(nèi)存中,并把相應(yīng)的各種符號(hào)函數(shù)解析定位好.然后,內(nèi)核模塊提供的各種函數(shù)才能真正被使用.當(dāng)模塊加載入內(nèi)核時(shí),系統(tǒng)將新加載模塊提供的資源和符號(hào)加到內(nèi)核符號(hào)表中;而當(dāng)模塊加載時(shí),內(nèi)核用符號(hào)表來解決模塊的資源引用問題.Linux允許模塊堆棧,即一個(gè)模塊可請(qǐng)求其他模塊為之服務(wù).通過這種通信機(jī)制,新加載的模塊可以訪問已加載模塊提供的資源[2].
內(nèi)核中有一個(gè)變量叫做module_list,定義在include/linux/module.h中,是一個(gè)全局變量.每當(dāng)用戶將一個(gè)模塊加載到內(nèi)核時(shí),這個(gè)模塊就會(huì)被添加到由module_list形成的鏈表中.必要時(shí),內(nèi)核就會(huì)檢索這個(gè)鏈表,找到該模塊,然后再使用其提供的函數(shù)或變量.
1.2 虛擬文件系統(tǒng)
Linux的最重要特征之一就是支持多種文件系統(tǒng),因此,它更加靈活并可以和許多其他操作系統(tǒng)共存.文件系統(tǒng)不僅包含著文件中的數(shù)據(jù),而且還有文件系統(tǒng)的結(jié)構(gòu)(屬性、操作等).每個(gè)實(shí)際文件系統(tǒng)從操作系統(tǒng)和系統(tǒng)服務(wù)中分離出來,它們之間通過一個(gè)接口層——虛擬文件系統(tǒng)(VFS)來通訊.虛擬文件系統(tǒng)所隱含的思想是,把表示很多不同種類文件系統(tǒng)的共同信息——通用文件模型放入內(nèi)核.Linux核心的其他部分及系統(tǒng)中運(yùn)行程序?qū)⒖吹浇y(tǒng)一的文件系統(tǒng).
把通用文件模型看作是面向?qū)ο蟮?在這里對(duì)象是一個(gè)結(jié)構(gòu),其中既定義了數(shù)據(jù)結(jié)構(gòu),也定義了其上的操作方法.VFS依賴于數(shù)據(jù)結(jié)構(gòu)來保存其對(duì)一個(gè)文件系統(tǒng)的一般表示.通用文件模型由超結(jié)塊、索引節(jié)點(diǎn)、目錄項(xiàng)和數(shù)據(jù)塊(文件)等對(duì)象類型(結(jié)構(gòu))組成[2].在相應(yīng)的目錄下有對(duì)應(yīng)結(jié)構(gòu)的操作方法的接口結(jié)構(gòu),如struct inode_operations,struct file_operations,成員幾乎都是一些函數(shù)指針.
用戶程序通過系統(tǒng)調(diào)用訪問通用的VFS.每個(gè)支持的文件系統(tǒng)必須實(shí)現(xiàn)一組函數(shù),而這組函數(shù)完成V FS所支持的操作.V FS了解它所支持的文件系統(tǒng)和完成每個(gè)操作的函數(shù)[3].V FS管理文件系統(tǒng)相關(guān)的系統(tǒng)調(diào)用,并把它們轉(zhuǎn)化成適應(yīng)文件系統(tǒng)類型的函數(shù),如圖2所示[2].
圖2 VFS與具體文件系統(tǒng)的關(guān)系示意圖Fig.2 Relationship of VFSand concrete file system
具體的文件系統(tǒng)可以設(shè)計(jì)成可加載模塊,在系統(tǒng)需要時(shí)進(jìn)行加載.掛載具體文件系統(tǒng)時(shí),VFS讀取它的超級(jí)塊,得到具體文件系統(tǒng)的拓?fù)浣Y(jié)構(gòu),并將這些信息映射到VFS超級(jí)塊結(jié)構(gòu)中.VFS在系統(tǒng)中保存著一組已安裝文件系統(tǒng)的鏈表及其VFS超塊,而每個(gè)VFS超塊包含一些信息及一個(gè)執(zhí)行特定功能的函數(shù)指針.
當(dāng)進(jìn)程或者shell命令訪問目錄和文件時(shí),shell命令及應(yīng)用程序分解成系統(tǒng)調(diào)用,進(jìn)入內(nèi)核空間,遍歷系統(tǒng)的VFS inode,而VFS的inode指向了具體文件系統(tǒng)的節(jié)點(diǎn).通過底層塊I/O函數(shù)調(diào)用IDE接口,再通過塊驅(qū)動(dòng)程序訪問塊設(shè)備,得到文件數(shù)據(jù).另外,還有一種特殊的文件系統(tǒng),如Proc或者Sysfs,它們操作內(nèi)存緩沖區(qū),在內(nèi)存緩沖區(qū)中存有相關(guān)系統(tǒng)管理信息.所有Linux文件系統(tǒng)使用一個(gè)通用buffer cache,來緩沖來自底層設(shè)備的數(shù)據(jù)以加速對(duì)包含此文件系統(tǒng)物理設(shè)備的存取[3].
此虛擬文件系統(tǒng)能夠管理在任何時(shí)刻映像到系統(tǒng)的不同文件系統(tǒng).它通過維護(hù)一個(gè)描述整個(gè)虛擬文件系統(tǒng)和實(shí)際已安裝文件系統(tǒng)的結(jié)構(gòu)來完成這個(gè)工作.VFS對(duì)文件系統(tǒng)共有的內(nèi)核上層及底層部分進(jìn)行了處理.上層處理如文件路徑的查找、文件的讀寫操作、從用戶空間向下傳遞到具體文件系統(tǒng)的部分;在底層進(jìn)行各種緩存的處理.
Proc文件系統(tǒng)真正顯示了Linux虛擬文件系統(tǒng)的能力,但事實(shí)上它并不存在.不管是Proc目錄,還是其子目錄和文件都不是真正的存在(不保存在硬盤或者其他磁盤中).Proc文件系統(tǒng)象一個(gè)真正的文件系統(tǒng)一樣向虛擬文件系統(tǒng)注冊(cè).然而,當(dāng)有對(duì)Proc中的文件和目錄的請(qǐng)求發(fā)生時(shí),VFS系統(tǒng)將從核心中的數(shù)據(jù)中臨時(shí)構(gòu)造這些文件和目錄.Proc文件系統(tǒng)提供給用戶一個(gè)核心內(nèi)部工作的可讀窗口. Linux核心模塊都在Proc文件系統(tǒng)中創(chuàng)建入口.
2.1 內(nèi)核模塊
在Linux模塊中,只能調(diào)用那些由內(nèi)核導(dǎo)出的函數(shù),而不能像其他應(yīng)用程序那樣調(diào)用庫(kù)函數(shù).因?yàn)長(zhǎng)inux內(nèi)核函數(shù)運(yùn)行在內(nèi)核空間,沒被鏈接到C庫(kù),所以在內(nèi)核空間無法調(diào)用C庫(kù)的函數(shù)[3].內(nèi)核函數(shù)通常定義在內(nèi)核源代碼的include目錄下,需要用的大都在include/Linux下.一個(gè)內(nèi)核模塊必須至少有兩個(gè)函數(shù),函數(shù)init_module()在該模塊加載到內(nèi)核的時(shí)候被調(diào)用,而函數(shù)cleanup_module()在模塊被卸載之前調(diào)用[3].
2.2 Proc文件系統(tǒng)程序
實(shí)現(xiàn)一個(gè)程序,它是內(nèi)核維護(hù)記錄學(xué)生名和學(xué)號(hào)的一張表格.利用Proc文件系統(tǒng)作為與內(nèi)核通信的手段,實(shí)現(xiàn)對(duì)文件的維護(hù)和操作.該程序由兩部分組成.一部分,作為內(nèi)核模塊在內(nèi)核運(yùn)行,在加載模塊時(shí),初始化表格,建立相應(yīng)的Proc文件;在卸載模塊時(shí),清除該表格和Proc文件;在加載后,則通過Proc文件系統(tǒng)接受用戶請(qǐng)求,實(shí)現(xiàn)對(duì)表格的維護(hù)操作.另一部分,實(shí)現(xiàn)為一個(gè)用戶態(tài)程序,它從命令行讀取用戶的命令,解析用戶命令;通過Proc文件系統(tǒng)將命令傳遞到內(nèi)核模塊,也可通過Proc文件系統(tǒng)從內(nèi)核模塊讀取信息[4].
2.2.1 解決方案 設(shè)計(jì)一個(gè)用戶態(tài)程序和一個(gè)核心態(tài)程序.用戶態(tài)程序包括添加記錄、刪除記錄、查看信息;核心態(tài)程序包括實(shí)現(xiàn)內(nèi)存的初始化、管理、卸載等功能.具體的通信過程:用戶態(tài)程序?qū)roc文件系統(tǒng)進(jìn)行讀和寫的操作.當(dāng)寫文件時(shí),內(nèi)核獲得用戶寫入的內(nèi)容,對(duì)寫入的內(nèi)容進(jìn)行處理和管理;當(dāng)用戶讀文件時(shí),內(nèi)核首先把內(nèi)存中保存的內(nèi)容寫到Proc文件中,用戶再讀些文件,得到想要讀的內(nèi)容[4].
2.2.2 主要代碼解析
利用Linux強(qiáng)大易用的可加載內(nèi)核模塊機(jī)制,可以靈活地?cái)U(kuò)充Linux內(nèi)核,廣泛利用在Linux設(shè)備驅(qū)動(dòng)和netfilter等方面的開發(fā)中.因此,在提高系統(tǒng)的安全性的同時(shí),也可以被攻擊者利用而非法入侵系統(tǒng).它猶如一把雙刃劍,在提供強(qiáng)大的靈活性同時(shí)有存在著極大的安全隱患,需要用戶謹(jǐn)慎使用.
[1] 熊海泉.Linux模塊實(shí)現(xiàn)機(jī)制剖析[J].科技廣場(chǎng),2006(2):7-8.
[2] 吳偉國(guó),李張,任廣臣.Linux內(nèi)核分析及高級(jí)編程[M].北京:電子工業(yè)出版社,2008:187.
[3] 毛德操,胡希明.Linux內(nèi)核源代碼情景分析[M].杭州:浙江大學(xué)出版社,2001:415-430.
[4] 羅宇,褚瑞.操作系統(tǒng)課程設(shè)計(jì)[M].北京:機(jī)械工業(yè)出版社,2005:106-120.
[5] CHERAM I.Linux內(nèi)核模塊編程——將/Proc作為輸入[EB/OL].[2006-12-16].http://www.egunao.com/os/ linux/18220.htm l.
Analysis in Depth on L inux Proc File System Programm ing
GUO Song,X IEWei-bo
(College of Computer Science&Technology,Huaqiao University,Quanzhou 362021,China)
The operation p rincip le of Linux loadable kernelmodule and virtual file system was discussed,and the advantages and disadvantages of the kernel p rogram running in micro kernel and integrated kernelwere compared.Base on this foundation,the Proc file system p rogramming is p roposed.W hich include the p rogramming p rocedure of kernel module and Proc file system,and to themain code was analyzed.Through a p rogramming demonstration,the framewo rk of Proc file system p rogramming is given to demonstrate the ability of Linux virtual file system.
Proc file system;Linux;kernelmodule;virtual file system
TP 311.1
A
(責(zé)任編輯:黃仲一 英文審校:吳逢鐵)
1000-5013(2010)05-0515-06
2009-10-23
謝維波((1964-),男,教授,主要從事信號(hào)處理與模式識(shí)別的研究.E-mail:xw blxf@hqu.edu.cn.
福建省廈門市科技計(jì)劃項(xiàng)目(3502Z20083047)