新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Linux可加載內(nèi)核模塊機(jī)制的研究與應(yīng)用

Linux可加載內(nèi)核模塊機(jī)制的研究與應(yīng)用

作者: 時(shí)間:2012-03-31 來源:網(wǎng)絡(luò) 收藏

關(guān)于模塊加載,可以用圖3.1來簡要描述:

圖3.1 模塊的裝入

insmod程序必須找到要求加載的內(nèi)核模塊,這些內(nèi)核模塊是已鏈接的目標(biāo)文件,與其他文件不同的是,它們被鏈接成可重定位映象即映象沒有被鏈接到特定地址上。insmod將執(zhí)行一個(gè)特權(quán)級(jí)系統(tǒng)調(diào)用來查找內(nèi)核的輸出符號(hào),這些符號(hào)都以符號(hào)名和數(shù)值形式如地址值成對保存。內(nèi)核輸出符號(hào)表被保存在內(nèi)核維護(hù)的模塊鏈表的第一個(gè)module結(jié)構(gòu)中。只有特殊符號(hào)才被添加,它們在內(nèi)核編譯與鏈接時(shí)確定。insmod將模塊讀入虛擬內(nèi)存并通過使用內(nèi)核輸出符號(hào)來修改其未解析的內(nèi)核函數(shù)和資源的引用地址。這些工作采取由insmod程序直接將符號(hào)的地址寫入模塊中相應(yīng)地址來進(jìn)行。

當(dāng)insmod修改完模塊對內(nèi)核輸出符號(hào)的引用后,它將再次使用特權(quán)級(jí)系統(tǒng)調(diào)用申請足夠的空間容納新模塊。內(nèi)核將為其分配一個(gè)新的module結(jié)構(gòu)以及足夠的內(nèi)核內(nèi)存來保存新模塊,并將其插入到內(nèi)核模塊鏈表的尾部,最后將新模塊標(biāo)志為UNINITIALIZED。insmod將模塊拷貝到已分配空間中,如果為它分配的內(nèi)核內(nèi)存已用完,將再次申請,但模塊被多次加載必然處于不同的地址。另外此重定位工作包括使用適當(dāng)?shù)刂穪硇薷哪K映象[5]。如果新模塊也希望將其符號(hào)輸出到系統(tǒng)中,insmod將為其構(gòu)造輸出符號(hào)映象表。每個(gè)內(nèi)核模塊必須包含模塊初始化和結(jié)束函數(shù),所以為了避免沖突它們的符號(hào)被設(shè)計(jì)成不輸出,但是insmod必須知道這些地址,這樣可以將它們傳遞給內(nèi)核。在所有這些工作完成以后,insmod將調(diào)用初始化代碼并執(zhí)行一個(gè)特權(quán)級(jí)系統(tǒng)調(diào)用將模塊的初始化和結(jié)束函數(shù)地址傳遞給內(nèi)核。當(dāng)將一個(gè)新模塊加載到內(nèi)核中時(shí),內(nèi)核必須更新其符號(hào)表并修改那些被新模塊使用的老模塊[6]。那些依賴于其他模塊的模塊必須在其符號(hào)表尾部維護(hù)一個(gè)引用鏈表并在其module數(shù)據(jù)結(jié)構(gòu)中指向它。內(nèi)核調(diào)用模塊的初始化函數(shù),如果成功將安裝此模塊。模塊的結(jié)束函數(shù)地址被存儲(chǔ)在其module結(jié)構(gòu)中,將在模塊卸載時(shí)由內(nèi)核調(diào)用,模塊的狀態(tài)最后被設(shè)置成RUNNING。

3.2 模塊的卸載

模塊可以使用rmmod命令刪除,但是請求加載模塊在其使用計(jì)數(shù)為0時(shí),自動(dòng)被系統(tǒng)刪除。kmod在其每次idle定時(shí)器到期時(shí)都執(zhí)行一個(gè)系統(tǒng)調(diào)用,將系統(tǒng)中所有不再使用的請求加載模塊刪除。

關(guān)于模塊卸載,可以用圖3.2來描述:

內(nèi)核中其他部分還在使用的模塊不能被卸載。例如系統(tǒng)中安裝了多個(gè)VFAT文件系統(tǒng)則不能卸載VFAT模塊。執(zhí)行l(wèi)smod將看到每個(gè)模塊的引用計(jì)數(shù)。模塊的引用計(jì)數(shù)被保存在其映象的第一個(gè)常字中,這個(gè)字還包含autoclean和visited標(biāo)志。如果模塊被標(biāo)記成autoclean,則內(nèi)核知道此模塊可以自動(dòng)卸載。visited標(biāo)志表示此模塊正被一個(gè)或多個(gè)文件系統(tǒng)部分使用,只要有其他部分使用此模塊則這個(gè)標(biāo)志被置位。每次系統(tǒng)要將沒有被使用的請求加載模塊刪除時(shí),內(nèi)核將在所有模塊中掃描,但是一般只查看那些被標(biāo)志為autoclean并處于running狀態(tài)的模塊。如果某模塊的 visited標(biāo)記被清除則它將被刪除。其他依賴于它的模塊將修改各自的引用域,表示它們間的依賴關(guān)系不復(fù)存在。此模塊占有的內(nèi)核內(nèi)存將被回收。

4. 的應(yīng)用

基本思想是:數(shù)據(jù)分組從網(wǎng)絡(luò)設(shè)備到用戶程序空間傳遞的過程中,減少數(shù)據(jù)拷貝次數(shù),減少系統(tǒng)調(diào)用,實(shí)現(xiàn)CPU的零參與,徹底消除CPU在這方面的負(fù)載。的實(shí)現(xiàn)分為實(shí)現(xiàn)DMA數(shù)據(jù)傳輸和地址映射兩個(gè)部分。其中DMA數(shù)據(jù)傳輸與本文關(guān)系不大,就不詳細(xì)敘述了,這里主要介紹應(yīng)用機(jī)制實(shí)現(xiàn)的地址映射。

地址映射的基本原理是在內(nèi)核空間申請內(nèi)存,通過proc文件系統(tǒng)和mmap函數(shù)將其映射到用戶空間來允許應(yīng)用程序訪問,這樣就消除了內(nèi)核空間到應(yīng)用程序空間的數(shù)據(jù)拷貝。地址映射部分的實(shí)現(xiàn)主要分為以下三步:

第一,建立LKM的基本結(jié)構(gòu),包括編寫初始化和結(jié)束函數(shù)等。

第二,聲明完成映射功能所需要的函數(shù),主要有分配和初始化內(nèi)核內(nèi)存函數(shù)init_mem(),釋放內(nèi)核內(nèi)存函數(shù)del_mem(),向內(nèi)核內(nèi)存輸入內(nèi)容的函數(shù)put_mem()等。

第三,在初始化函數(shù)中應(yīng)用第二步建立的函數(shù)分配一塊內(nèi)存空間、輸入內(nèi)容、建立proc文件系統(tǒng)入口。在結(jié)束函數(shù)中釋放已分配的內(nèi)核內(nèi)存,刪除proc文件系統(tǒng)入口。

編寫應(yīng)用程序測試該LKM,發(fā)現(xiàn)已經(jīng)達(dá)到了映射內(nèi)核內(nèi)存到應(yīng)用程序空間的目的。在實(shí)現(xiàn)的過程中采用LKM機(jī)制不但便于調(diào)試而且大大減少了開發(fā)時(shí)間。

linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)


關(guān)鍵詞: LKM Linux 零拷貝

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉