第9章 模塊的動態(tài)加載和系統(tǒng)配置.ppt_第1頁
第9章 模塊的動態(tài)加載和系統(tǒng)配置.ppt_第2頁
第9章 模塊的動態(tài)加載和系統(tǒng)配置.ppt_第3頁
第9章 模塊的動態(tài)加載和系統(tǒng)配置.ppt_第4頁
第9章 模塊的動態(tài)加載和系統(tǒng)配置.ppt_第5頁
已閱讀5頁,還剩70頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第9章模塊的動態(tài)加載和系統(tǒng)配置 第9章模塊的動態(tài)加載和系統(tǒng)配置 本章介紹了Linux內(nèi)核動態(tài)加載功能模塊的工作原理 分析了Linux內(nèi)核中的系統(tǒng)配置結(jié)構(gòu) 解釋了Makefile和配置文件的格式以及配置語句的含義 最后給出一個簡單的例子 說明如何將自行開發(fā)的代碼加入到Linux內(nèi)核中 9 1模塊的動態(tài)加載 操作系統(tǒng)通常由內(nèi)核和一些系統(tǒng)服務(wù)程序 命令解釋 庫文件 鏈接和編譯程序等 組成 內(nèi)核是操作系統(tǒng)的靈魂 它為用戶進程提供了一個虛擬機接口 用戶進程可以并行運行 公平的占用系統(tǒng)資源而互不干擾 9 1模塊的動態(tài)加載 操作系統(tǒng)通常由內(nèi)核和一些系統(tǒng)服務(wù)程序 命令解釋 庫文件 鏈接和編譯程序等 組成 內(nèi)核是操作系統(tǒng)的靈魂 它為用戶進程提供了一個虛擬機接口 用戶進程可以并行運行 公平的占用系統(tǒng)資源而互不干擾 從結(jié)構(gòu)上來分 可將操作系統(tǒng)分為微內(nèi)核結(jié)構(gòu)和單塊結(jié)構(gòu)兩類 WindowsNT和MINIX是典型的微內(nèi)核操作系統(tǒng) 而Linux則是單塊結(jié)構(gòu)的操作系統(tǒng) 微內(nèi)核結(jié)構(gòu)可方便地在系統(tǒng)中添加新的組件 而單塊結(jié)構(gòu)卻不容易做到這一點 為此 Linux系統(tǒng)使用可動態(tài)加載和卸載的內(nèi)核模塊 LoadableKernelModules LKMs 可方便地在內(nèi)核中添加新的組件或卸載不再需要的內(nèi)核組件 Linux使用insmod來顯式加載內(nèi)核模塊 使用rmmod來卸載模塊 同時內(nèi)核自身也可以請求內(nèi)核后臺進程kerneld來加載與卸載模塊 Linux模塊大多數(shù)是設(shè)備驅(qū)動程序以及偽設(shè)備驅(qū)動程序模塊 如網(wǎng)絡(luò)設(shè)備和文件系統(tǒng)等 動態(tài)可加載代碼的優(yōu)點是可以讓內(nèi)核保持很小的尺寸并非常靈活 模塊機制可以無需重構(gòu)內(nèi)核并頻繁重新啟動來嘗試運行新內(nèi)核代碼 用戶可以根據(jù)自己系統(tǒng)的需要構(gòu)筑自己的私有內(nèi)核 Linux源碼的公開更是為改造其內(nèi)核 重建有特殊要求的操作系統(tǒng)提供了可能 模塊必須能夠找到其需要使用的內(nèi)核資源 例如模塊需要分配內(nèi)存時 要調(diào)用內(nèi)核的內(nèi)存分配例程kmalloc 但在構(gòu)造模塊時并不知道kmalloc 在內(nèi)存中何處 這樣內(nèi)核必須在使用這些模塊前修改模塊中對kmalloc 的引用地址 內(nèi)核在其內(nèi)核符號表中維護著一個內(nèi)核資源鏈表這樣當加載模塊時它能夠解析出模塊中對內(nèi)核資源的引用 Linux還允許存在模塊堆棧 它在模塊之間相互調(diào)用時使用 例如 因為VFAT VirtuaIFileAllocationTable 文件系統(tǒng)是從FAT FileAllocationTable 文件系統(tǒng)中擴展而來 VFAT文件系統(tǒng)模塊可能需要FAT文件系統(tǒng)模塊的服務(wù) 某個模塊對其他模塊的服務(wù)或資源的需求類似于模塊對內(nèi)核本身資源或服務(wù)的請求 不過此時所請求的服務(wù)是來自另外一個事先已加載的模塊 當加載模塊時 內(nèi)核就把新近加載模塊輸出的所有資源和符號添加到內(nèi)核符號表 Kernel Symbol Table 中 在 proc ksyms 里面的每一個表項代表著一個公共的內(nèi)核符號 這就是內(nèi)核符號表 這些內(nèi)核符號是可以被LKM引用的 LKM中所存取的每一個符號 像函數(shù)名 也會被列在這個文件里面 在該文件中可以看到LKM到底可以調(diào)用那些函數(shù) 當試圖卸載某個模塊時 內(nèi)核需要知道此模塊是否已經(jīng)沒有被使用 同時它需要有種方法來通知此將卸載模塊 模塊必須能夠在從內(nèi)核種刪除之前釋放其分配的所有系統(tǒng)資源 如內(nèi)核內(nèi)存或中斷 當模塊被卸載時 內(nèi)核將從內(nèi)核符號表中刪除所有與之對應(yīng)的符號 但是 內(nèi)核模塊的引入也帶來了如下問題 但是 內(nèi)核模塊的引入也帶來了如下問題 1 有可能同時帶來與內(nèi)核模塊相關(guān)的性能與內(nèi)存損失 可加載模塊的代碼一般較長 且額外的數(shù)據(jù)結(jié)構(gòu)可能會占據(jù)一些內(nèi)存 對內(nèi)核資源的間接使用也可能帶來效率方面的問題 對系統(tǒng)性能和內(nèi)存利用有負面影響 但是 內(nèi)核模塊的引入也帶來了如下問題 1 有可能同時帶來與內(nèi)核模塊相關(guān)的性能與內(nèi)存損失 可加載模塊的代碼一般較長 且額外的數(shù)據(jù)結(jié)構(gòu)可能會占據(jù)一些內(nèi)存 對內(nèi)核資源的間接使用也可能帶來效率方面的問題 對系統(tǒng)性能和內(nèi)存利用有負面影響 2 一旦Linux模塊被加載 則和普通內(nèi)核代碼一樣成為內(nèi)核的一部分 具有與其他內(nèi)核代碼相同的權(quán)限與職責 因此 Linux內(nèi)核模塊也可以象所有內(nèi)核代碼和設(shè)備驅(qū)動一樣使內(nèi)核崩潰 但是 內(nèi)核模塊的引入也帶來了如下問題 1 有可能同時帶來與內(nèi)核模塊相關(guān)的性能與內(nèi)存損失 可加載模塊的代碼一般較長 且額外的數(shù)據(jù)結(jié)構(gòu)可能會占據(jù)一些內(nèi)存 對內(nèi)核資源的間接使用也可能帶來效率方面的問題 對系統(tǒng)性能和內(nèi)存利用有負面影響 2 一旦Linux模塊被加載 則和普通內(nèi)核代碼一樣成為內(nèi)核的一部分 具有與其他內(nèi)核代碼相同的權(quán)限與職責 因此 Linux內(nèi)核模塊也可以象所有內(nèi)核代碼和設(shè)備驅(qū)動一樣使內(nèi)核崩潰 3 為了內(nèi)核模塊訪問所有內(nèi)核資源 內(nèi)核必須維護符號表 并在裝入和卸載模塊時修改這些符號表 但是 內(nèi)核模塊的引入也帶來了如下問題 1 有可能同時帶來與內(nèi)核模塊相關(guān)的性能與內(nèi)存損失 可加載模塊的代碼一般較長 且額外的數(shù)據(jù)結(jié)構(gòu)可能會占據(jù)一些內(nèi)存 對內(nèi)核資源的間接使用也可能帶來效率方面的問題 對系統(tǒng)性能和內(nèi)存利用有負面影響 2 一旦Linux模塊被加載 則和普通內(nèi)核代碼一樣成為內(nèi)核的一部分 具有與其他內(nèi)核代碼相同的權(quán)限與職責 因此 Linux內(nèi)核模塊也可以象所有內(nèi)核代碼和設(shè)備驅(qū)動一樣使內(nèi)核崩潰 3 為了內(nèi)核模塊訪問所有內(nèi)核資源 內(nèi)核必須維護符號表 并在裝入和卸載模塊時修改這些符號表 4 有些模塊要求利用其他模塊的功能 因此 內(nèi)核要維護模塊之間的依賴性 5 內(nèi)核必須能夠在卸載模塊時通知模塊 并且要釋放分配給模塊的內(nèi)存和中斷等資源 6 內(nèi)核版本和模塊版本的不兼容 也可能導致系統(tǒng)崩潰 因此 嚴格的版本檢查是必需的 9 1 1模塊的加載 9 1 1模塊的加載 有兩種方法可用來加載模塊 1 利用insmod命令手工將模塊插入內(nèi)核 9 1 1模塊的加載 有兩種方法可用來加載模塊 1 利用insmod命令手工將模塊插入內(nèi)核 2 由內(nèi)核在必要時加載模塊 稱為 需求加載 當內(nèi)核發(fā)現(xiàn)有必要加載某個模塊時 如用戶安裝了內(nèi)核中不存在的文件系統(tǒng)時 內(nèi)核將請求內(nèi)核后臺進程 kerneld 準備加載適當?shù)哪K 這個內(nèi)核后臺進程僅僅是一個帶有超級用戶權(quán)限的普通用戶進程 當系統(tǒng)啟動時它也被啟動并為內(nèi)核打開了一個進程間通訊 IPC 通道 內(nèi)核可以利用該通道向Kerneld進程發(fā)送任務(wù)的執(zhí)行請求 Kerneld進程的主要功能是加載和卸載模塊 另外 該進程也負責其他一些任務(wù) 例如打開和關(guān)閉PPP鏈接等 kerneld自身并不執(zhí)行這些任務(wù) 它通過某些程序如insmod來做此工作 因此 該進程實際是代表內(nèi)核進行調(diào)度的代理 執(zhí)行insmod命令時 必須指定要加載模塊的位置 對需求加載的內(nèi)核模塊 通常保存在 lib modules kernel version 和系統(tǒng)的其他程序一樣 內(nèi)核模塊實際是經(jīng)連接的目標文件 但模塊是可重定位的 也就是說 為了讓裝入的模塊和已有的內(nèi)核組件之間可以互相訪問 模塊不能連接為從特定地址執(zhí)行的映像文件 模塊可以是a out或elf格式的目標文件 insmod利用一個特權(quán)系統(tǒng)調(diào)用 可找到內(nèi)核的導出符號表 符號成對出現(xiàn) 一個是符號名稱 另外一個是符號的值 例如符號的地址 內(nèi)核維護一個由module list指針指向的module鏈表 其中第一個module數(shù)據(jù)結(jié)構(gòu)保存有內(nèi)核的導出符號表 見圖9 1 并不是所有的內(nèi)核符號均在符號表中導出 而只有一些特殊的符號才被添加到符號表中 例如 request irq 是一個導出符號 它是一個內(nèi)核例程 可由驅(qū)動程序申請控制某個特定的系統(tǒng)中斷 利用ksyms命令或查看 proc ksyms文件內(nèi)容 可非常方便地看到所有的內(nèi)核導出符號及其符號值 利用ksyms命令 不僅可以看到內(nèi)核的所有符號 也可以看到只由以加載模塊導出的符號 insmod命令將模塊讀到它本身的虛擬內(nèi)存中 然后利用內(nèi)核導出的符號表 修正尚未解析的對內(nèi)核例程的引用 這種修正實際是對模塊在內(nèi)存中的映像進行修正 insmod將符號的地址寫入模塊中適當?shù)奈恢枚鴮崿F(xiàn)修正 圖9 1裝入VFAT和FAT之后的內(nèi)核模塊表 insmod命令修正模塊對內(nèi)核符號的引用之后 再次利用特權(quán)系統(tǒng)調(diào)用請求內(nèi)核分配足夠的物理內(nèi)存空間保存新的模塊 內(nèi)核將分配新的module數(shù)據(jù)結(jié)構(gòu)以及足夠的內(nèi)核內(nèi)存 并將新模塊添加在內(nèi)核模塊表的末尾 新的內(nèi)核模塊標記為Uninitialized 未初始化 圖9 1是裝入VFAT和FAT模塊之后的內(nèi)核模塊表 圖中并沒有表示出第一個模塊 它實際是一個偽模塊 僅僅用來保存內(nèi)核的導出符號表 利用lsmod命令可列出所有已加載的內(nèi)核模塊以及它們的內(nèi)在依賴性 內(nèi)核為新模塊分配的內(nèi)核內(nèi)存映射到insmod進程的地址空間中 這樣 insmod就可以將模塊復制到新分配的內(nèi)存中 insmod還對模塊進行重新定位 經(jīng)重定位之后 新的模塊就可以從新分配的內(nèi)核地址開始運行了 顯然 模塊不能期望自己能夠在不同的Linux系統(tǒng) 或前后兩次裝入時被加載到相同地址 重定位操作可通過對模塊映像中適當?shù)牡刂愤M行修正而解決這一問題 新的模塊也要向內(nèi)核導出符號 由insmod建立相應(yīng)的符號表 每個內(nèi)核模塊必須包含模塊的初始化和清除例程 這些例程作為每個模塊均具備的例程而不被導出 但insmod必須知道它們的地址 并將地址傳遞給內(nèi)核 insmod同樣利用特權(quán)系統(tǒng)調(diào)用將模塊的初始化和清除例程地址傳遞給內(nèi)核 新的模塊添加到內(nèi)核之后 它必須更新內(nèi)核符號集并修改使用新模塊的模塊 由其他模塊依賴的模塊必須在自身符號表的末尾維護一個引用表 并指向其他模塊的module結(jié)構(gòu) 例如 圖9 1表明VFAT文件系統(tǒng)模塊依賴于FAT文件系統(tǒng)模塊 因此 FAT模塊包含一個對VFAT模塊的引用 該引用在裝入VFAT模塊時添加 內(nèi)核成功調(diào)用模塊的初始化例程之后繼續(xù)模塊的安裝 最后 模塊狀態(tài)被設(shè)置為Running 運行 模塊的清除例程保存在module數(shù)據(jù)結(jié)構(gòu)中 在卸載模塊時由內(nèi)核調(diào)用 9 1 2模塊的卸載 和模塊的加載類似 可利用rmmod命令手工卸載模塊 當對需求加載的模塊則由kerneld在不再需要時自動卸載 每次kerneld的空閑定時器到期時 它會利用系統(tǒng)調(diào)用將當前不再使用的需求加載模塊從內(nèi)核中移走 啟動kerneld時指定該定時器的時間 通常的時間為180秒 如果內(nèi)核的其他部分依賴于裝入的模塊時 該模塊不能卸載 例如 如果掛裝了FAT文件系統(tǒng) 則不能卸載已裝入的FAT文件系統(tǒng)模塊 lsmod命令的輸出會顯示已安裝模塊的使用計數(shù) 例如 Module pages Usedby msdos51vfat41 autoclean fat62 autoclean 使用計數(shù)就是依賴于該模塊的內(nèi)核實體個數(shù) 模塊的使用計數(shù)保存在模塊映像的第一個長整型中 但是 這一長整型中還包含有AUTOCLEAN和VISITED標志 這兩個標志均由需求加載的模塊使用 具有AUTOCLEAN標志的模塊是系統(tǒng)認為可以自動卸載的模塊 具有VISITED標志的模塊表明正由其他內(nèi)核組件使用 當任何其他內(nèi)核組件使用該模塊是設(shè)置該標志 當kerneld請求系統(tǒng)移走不使用的需求加載模塊時 系統(tǒng)首先尋找可以移走的模塊 但系統(tǒng)只查看標記為AUTOCLEAN 并且狀態(tài)處于RUNNING的模塊 如果上述模塊的VISITED標志被清除 則系統(tǒng)將卸載該模塊 否則系統(tǒng)會清除VISITED標志并查看下一個模塊 假定某個模塊是可卸載的 則系統(tǒng)調(diào)用其清除例程釋放分配該模塊的內(nèi)核資源 相應(yīng)的module數(shù)據(jù)結(jié)構(gòu)被標志為DELETED并從內(nèi)核模塊鏈表中斷開 所有由該模塊依賴的模塊 系統(tǒng)會修改它們的引用表以便取消依賴性 最后 系統(tǒng)釋放模塊的內(nèi)核內(nèi)存 9 1 3內(nèi)核模塊的管理 9 1 3內(nèi)核模塊的管理 在Linux里 除了直接修改系統(tǒng)核心的源代碼 把設(shè)備驅(qū)動程序加進核心里以外 還可以把設(shè)備驅(qū)動程序作為可加載的模塊 由系統(tǒng)管理員動態(tài)地加載它 使之成為核心的一部分 也可以由系統(tǒng)管理員把已加載地模塊動態(tài)地卸載下來 Linux的模塊可以用C語言編寫 用gcc編譯成目標文件 不進行鏈接 作為 o文件存在 為此需要在gcc命令行里加上 c的參數(shù) 在編譯時 還應(yīng)該在gcc的命令行里加上這樣的參數(shù) D KERNEL DMODULE 由于在不鏈接時 gcc只允許一個輸入文件 因此一個模塊的所有部分都必須在一個文件里實現(xiàn) 編譯好的模塊 o放 lib modules xxxx misc下 xxxx表示核心版本 如在核心版本為2 0 30時應(yīng)該為 lib modules 2 0 30 misc 然后用depmod a使此模塊成為可加載模塊 模塊用insmod命令加載 用rmmod命令來卸載 并可以用lsmod命令來查看所有已加載的模塊的狀態(tài) 利用insmod命令可手工裝入內(nèi)核模塊 利用lsmod可查看當前裝入的內(nèi)核模塊以及需求加載模塊的使用計數(shù)及標志信息 利用rmmod則可以卸載指定的模塊 編寫模塊程序的時候 必須提供兩個函數(shù) 一個是intinit module void 供insmod在加載此模塊的時候自動調(diào)用 負責進行設(shè)備驅(qū)動程序的初始化工作 init module返回0以表示初始化成功 返回負數(shù)表示失敗 另一個函數(shù)是voidcleanup module void 在模塊被卸載時調(diào)用 負責進行設(shè)備驅(qū)動程序的清除工作 在成功的向系統(tǒng)注冊了設(shè)備驅(qū)動程序后 調(diào)用register chrdev成功后 就可以用mknod命令來把設(shè)備映射為一個特別文件 其它程序使用這個設(shè)備的時候 只要對此特別文件進行操作就行了 9 2Linux內(nèi)核配置系統(tǒng) 隨著Linux操作系統(tǒng)的廣泛應(yīng)用 特別是Linux在嵌入式領(lǐng)域的發(fā)展 越來越多的人開始投身到Linux內(nèi)核級的開發(fā)中 面對日益龐大的Linux內(nèi)核源代碼 開發(fā)者在完成自己的內(nèi)核代碼后 都將面臨著同樣的問題 即如何將源代碼融入到Linux內(nèi)核中 增加相應(yīng)的Linux配置選項 并最終被編譯進Linux內(nèi)核 這就需要了解Linux的內(nèi)核配置系統(tǒng) Linux內(nèi)核是由分布在全球的Linux愛好者共同開發(fā)的 Linux內(nèi)核每天都面臨著許多新的變化 但是 Linux內(nèi)核的組織并沒有出現(xiàn)混亂的現(xiàn)象 反而顯得非常的簡潔 而且具有很好的擴展性 開發(fā)人員可以很方便的向Linux內(nèi)核中增加新的內(nèi)容 原因之一就是Linux采用了模塊化的內(nèi)核配置系統(tǒng) 從而保證了內(nèi)核的擴展性 9 2 1配置系統(tǒng)的基本結(jié)構(gòu) 9 2 1配置系統(tǒng)的基本結(jié)構(gòu) Linux內(nèi)核的配置系統(tǒng)由三個部分組成 1 Makefile 分布在Linux內(nèi)核源代碼中的Makefile定義Linux內(nèi)核的編譯規(guī)則 2 配置文件 config in 給用戶提供配置選擇的功能 3 配置工具 包括配置命令解釋器 對配置腳本中使用的配置命令進行解釋 和配置用戶界面 提供基于字符界面 基于Ncurses圖形界面以及基于Xwindows圖形界面的用戶配置界面 各自對應(yīng)于Makeconfig Makemenuconfig和Makexconfig 這些配置工具都是使用腳本語言 如Tcl TK Perl編寫的 也包含一些用C編寫的代碼 除非是配置系統(tǒng)的維護者 一般的內(nèi)核開發(fā)者無須了解配置系統(tǒng)的原理 只需要知道如何使用配置系統(tǒng) 如何編寫Makefile和配置文件就可以 所以 本節(jié)只對Makefile和配置文件進行討論 凡是涉及到與具體CPU體系結(jié)構(gòu)相關(guān)的內(nèi)容 都以ARM為例 這樣不僅可以將討論的問題明確化 而且對內(nèi)容本身不產(chǎn)生影響 9 2 2Makefile Makefile的作用是根據(jù)配置的情況 構(gòu)造出需要編譯的源文件列表 然后分別編譯 并把目標代碼鏈接到一起 最終形成Linux內(nèi)核二進制文件 由于Linux內(nèi)核源代碼是按照樹形結(jié)構(gòu)組織的 所以Makefile也被分布在目錄樹中 Linux內(nèi)核中的Makefile以及與Makefile直接相關(guān)的文件有 Makefile 頂層Makefile 是整個內(nèi)核配置 編譯的總體控制文件 config 內(nèi)核配置文件 包含由用戶選擇的配置選項 用來存放內(nèi)核配置后的結(jié)果 如makeconfig arch Makefile 位于各種CPU體系目錄下的Makefile 如arch arm Makefile 是針對特定平臺的Makefile 各個子目錄下的Makefile 比如drivers Makefile 負責所在子目錄下源代碼的管理 Rules make 規(guī)則文件 被所有的Makefile使用 用戶通過makeconfig配置后 產(chǎn)生了 config 頂層Makefile讀入 config中的配置選擇 頂層Makefile有兩個主要的任務(wù) 產(chǎn)生vmlinux文件和內(nèi)核模塊 module 為了達到此目的 頂層Makefile遞歸的進入到內(nèi)核的各個子目錄中 分別調(diào)用位于這些子目錄中的Makefile 至于到底進入哪些子目錄 取決于內(nèi)核的配置 在頂層Makefile中 有一句 includearch ARCH Makefile 包含了特定CPU體系結(jié)構(gòu)下的Makefile 這個Makefile中包含了平臺相關(guān)的信息 位于各個子目錄下的Makefile同樣也根據(jù) config給出的配置信息 構(gòu)造出當前配置下需要的源文件列表 并在文件的最后有include TOPDIR Rules make Rules make文件起著非常重要的作用 它定義了所有Makefile共用的編譯規(guī)則 比如 如果需要將本目錄下所有的c程序編譯成匯編代碼 需要在Makefile中有以下的編譯規(guī)則 s c CC CFLAGS S o 有很多子目錄下都有同樣的要求 就需要在各自的Makefile中包含此編譯規(guī)則 這會比較麻煩 而Linux內(nèi)核中則把此類的編譯規(guī)則統(tǒng)一放置到Rules make中 并在各自的Makefile中包含進了Rules make includeRules make 這樣就避免了在多個Makefile中重復同樣的規(guī)則 對于上面的例子 在Rules make中對應(yīng)的規(guī)則為 s c CC CFLAGS EXTRA CFLAGS CFLAGS F CFLAGS S o Makefile中的變量頂層Makefile定義并向環(huán)境中輸出了許多變量 為各個子目錄下的Makefile傳遞一些信息 有些變量 比如SUBDIRS 不僅在頂層Makefile中定義并且賦初值 而且在arch Makefile還作了擴充 常用的變量有以下幾類 1 版本信息版本信息有 VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION和KERNELRELEASE 版本信息定義了當前內(nèi)核的版本 例如VERSION 2 PATCHLEVEL 4 SUBLEVEL 18 EXATAVERSION rmk7 它們共同構(gòu)成內(nèi)核的發(fā)行版本KERNELRELEASE 2 4 18 rmk7 2 CPU體系結(jié)構(gòu) ARCH在頂層Makefile的開頭 用ARCH定義目標CPU的體系結(jié)構(gòu) 比如ARCH arm等 許多子目錄的Makefile中 要根據(jù)ARCH的定義選擇編譯源文件的列表 3 路徑信息 TOPDIR和SUBDIRSTOPDIR定義了Linux內(nèi)核源代碼所在的根目錄 例如 各個子目錄下的Makefile通過 TOPDIR Rules make就可以找到Rules make的位置 SUBDIRS定義了一個目錄列表 在編譯內(nèi)核或模塊時 頂層Makefile就是根據(jù)SUBDIRS來決定進入哪些子目錄 SUBDIRS的值取決于內(nèi)核的配置 在頂層Makefile中SUBDIRS賦值為kerneldriversmmfsnetipclib 根據(jù)內(nèi)核的配置情況 在arch Makefile中擴充了SUBDIRS的值 4 內(nèi)核組成信息 HEAD CORE FILES NETWORKS DRIVERS LIBSLinux內(nèi)核文件vmlinux是由以下規(guī)則產(chǎn)生的 vmlinux CONFIGURATION init main oinit version olinuxsubdirs LD LINKFLAGS HEAD init main oinit version o start group CORE FILES DRIVERS NETWORKS LIBS end group ovmlinux可以看出 vmlinux是由HEAD main o version o CORE FILES DRIVERS NETWORKS和LIBS組成的 這些變量 如HEAD 都是用來定義連接生成vmlinux的目標文件和庫文件列表 其中 HEAD在arch Makefile中定義 用來確定被最先鏈接進vmlinux的文件列表 例如 對于ARM系列的CPU HEAD定義為 HEAD arch arm kernel head PROCESSOR o arch arm kernel init task o表明head PROCESSOR o和init task o需要最先被鏈接到vmlinux中 PROCESSOR為armv或armo 取決于目標CPU CORE FILES NETWORK DRIVERS和LIBS在頂層Makefile中定義 并且由arch Makefile根據(jù)需要進行擴充 CORE FILES對應(yīng)著內(nèi)核的核心文件 有kernel kernel o mm mm o fs fs o ipc ipc o 可以看出 這些是組成內(nèi)核最為重要的文件 同時 arch arm Makefile對CORE FILES進行了擴充 arch arm Makefile Ifwehaveamachine specificdirectory thenincludeitinthebuild MACHDIR arch arm mach MACHINE ifeq MACHDIR wildcard MACHDIR SUBDIRS MACHDIR CORE FILES MACHDIR MACHINE o CORE FILES endifHEAD arch arm kernel head PROCESSOR o arch arm kernel init task oSUBDIRS arch arm kernelarch arm mmarch arm libarch arm nwfpeCORE FILES arch arm kernel kernel oarch arm mm mm o CORE FILES LIBS arch arm lib lib a LIBS 5 編譯信息 CPP CC AS LD AR CFLAGS LINKFLAGS在Rules make中定義的是編譯的通用規(guī)則 具體到特定的場合 需要明確給出編譯環(huán)境 編譯環(huán)境就是在以上的變量中定義的 針對交叉編譯的要求 定義了CROSS COMPILE 如 CROSS COMPILE arm linux CC CROSS COMPILE gccLD CROSS COMPILE ld CROSS COMPILE定義了交叉編譯器前綴arm linux 表明所有的交叉編譯工具都是以arm linux 開頭的 所以在各個交叉編譯器工具之前 都加入了 CROSS COMPILE 以組成一個完整的交叉編譯工具文件名 比如arm linux gcc CFLAGS定義了傳遞給C編譯器的參數(shù) LINKFLAGS是鏈接生成vmlinux時 由鏈接器使用的參數(shù) LINKFLAGS在arm Makefile中定義 如 arch arm MakefileLINKFLAGS p X Tarch arm vmlinux lds 6 配置變量CONFIG config文件中有許多的配置變量等式 用來說明用戶配置的結(jié)果 例如CONFIG MODULES y表明用戶選擇了Linux內(nèi)核的模塊功能 config被頂層Makefile包含后 就形成許多的配置變量 每個配置變量具有確定的值 y表示本編譯選項對應(yīng)的內(nèi)核代碼被靜態(tài)編譯進Linux內(nèi)核 m表示本編譯選項對應(yīng)的內(nèi)核代碼被編譯成模塊 n表示不選擇此編譯選項 如果根本就沒有選擇 那么配置變量的值為空 2 Rules make變量Rules make是編譯規(guī)則文件 所有的Makefile中都會包括Rules make Rules make文件定義了許多變量 最為重要是那些編譯 鏈接列表變量 O OBJS L OBJS OX OBJS LX OBJS 本目錄下需要編譯進Linux內(nèi)核vmlinux的目標文件列表 其中OX OBJS和LX OBJS中的 X 表明目標文件使用了EXPORT SYMBOL輸出符號 M OBJS MX OBJS 本目錄下需要被編譯成可裝載模塊的目標文件列表 同樣 MX OBJS中的 X 表明目標文件使用了EXPORT SYMBOL輸出符號 O TARGET L TARGET 每個子目錄下都有一個O TARGET或L TARGET Rules make首先從源代碼編譯生成O OBJS和OX OBJS中所有的目標文件 然后使用 LD r把它們鏈接成一個O TARGET或L TARGET O TARGET以 o結(jié)尾 而L TARGET以 a結(jié)尾 3 Makefile子目錄 3 Makefile子目錄 子目錄Makefile用來控制本級目錄以下源代碼的編譯規(guī)則 下面通過一個例子來講解子目錄Makefile的組成 Makefileforthelinuxkernel Allofthe potential objectsthatexportsymbols Thislistcomesfrom grep lEXPORT SYMBOL hc export objs tc o Objectfilelists obj y obj m obj n obj obj CONFIG TC tc oobj CONFIG ZS zs oobj CONFIG VT lk201 olk201 map olk201 remap o Filesthatarebothresidentandmodular removefrommodular obj m filter out obj y obj m TranslatetoRules makelists L TARGET tc aL OBJS sort filter out export objs obj y LX OBJS sort filter export objs obj y M OBJS sort filter out export objs obj m MX OBJS sort filter export objs obj m include TOPDIR Rules make 1 注釋對Makefile的說明和解釋 由 開始 2 編譯目標定義類似于obj CONFIG TC tc o的語句是用來定義編譯的目標 是子目錄Makefile中最重要的部分 編譯目標定義那些在本子目錄下 需要編譯到Linux內(nèi)核中的目標文件列表 為了只在用戶選擇了此功能后才編譯 所有的目標定義都融合了對配置變量的判斷 前面說過 每個配置變量取值范圍是 y n m和空 obj CONFIG TC 分別對應(yīng)著obj y obj n obj m obj 如果CONFIG TC配置為y 那么tc o就進入了obj y列表 obj y為包含到Linux內(nèi)核vmlinux中的目標文件列表 obj m為編譯成模塊的目標文件列表 obj n和obj 中的文件列表被忽略 配置系統(tǒng)就根據(jù)這些列表的屬性進行編譯和鏈接 export objs中的目標文件都使用了EXPORT SYMBOL 定義了公共的符號 以便可裝載模塊使用 在tc c文件的最后部分 有 EXPORT SYMBOL search tc card 表明tc o有符號輸出 這里需要指出的是 對于編譯目標的定義 存在著兩種格式 分別是老式定義和新式定義 老式定義就是前面Rules make使用的那些變量 新式定義就是obj y obj m obj n和obj Linux內(nèi)核推薦使用新式定義 不過由于Rules make不理解新式定義 需要在Makefile中的適配段將其轉(zhuǎn)換成老式定義 3 適配段適配段的作用是將新式定義轉(zhuǎn)換成老式定義 在上面的例子中 適配段就是將obj y和obj m轉(zhuǎn)換成Rules make能夠理解的L TARGET L OBJS LX OBJS M OBJS MX OBJS L OBJS sort filter out export objs obj y 定義了L OBJS的生成方式 在obj y的列表中過濾掉export objs tc o 然后排序并去除重復的文件名 這里使用到了GNUMake的一些特殊功能 具體的含義可參考Make的文檔 infomake 4 include TOPDIR Rules make 9 2 3配置文件 9 2 3配置文件 除了Makefile的編寫 另外一個重要的工作就是把新功能加入到Linux的配置選項中 提供此項功能的說明 讓用戶有機會選擇此項功能 所有的這些都需要在config in文件中用配置語言來編寫配置腳本 在Linux內(nèi)核中 配置命令有多種方式 以字符界面配置 makeconfig 為例 頂層Makefile調(diào)用scripts Configure 按照arch arm config in來進行配置 命令執(zhí)行完后產(chǎn)生文件 config 其中保存著配置信息 下一次再做makeconfig將產(chǎn)生新的 config文件 原 config被改名為 config old 1 配置語言 1 頂層菜單mainmenu name prompt prompt 是用 或 包圍的字符串 與 的區(qū)別是 中可使用 引用變量的值 mainmenu name設(shè)置最高層菜單的名字 它只在makexconfig時才會顯示 2 詢問語句bool prompt symbol hex prompt symbol word int prompt symbol word string prompt symbol word tristate prompt symbol 詢問語句首先顯示一串提示符 prompt 等待用戶輸入 并把輸入的結(jié)果賦給 symbol 所代表的配置變量 不同的詢問語句的區(qū)別在于它們接受的輸入數(shù)據(jù)類型不同 比如bool接受布爾類型 y或n hex接受16進制數(shù)據(jù) 有些詢問語句還有第三個參數(shù) word 用來給出默認值 3 定義語句define bool symbol word define hex symbol word define int symbol word define string symbol word define tristate symbol word 不同于詢問語句等待用戶輸入 定義語句顯式的給配置變量 symbol 賦值 word 3 定義語句define bool symbol word define hex symbol word define int symbol word define string symbol word define tristate symbol word 不同于詢問語句等待用戶輸入 定義語句顯式的給配置變量 symbol 賦值 word 4 依賴語句dep bool prompt symbol dep dep mbool prompt symbol dep dep hex prompt symbol word dep dep int prompt symbol word dep dep string prompt symbol word dep dep tristate prompt symbol dep 與詢問語句類似 依賴語句也是定義新的配置變量 不同的是 配置變量 symbol 的取值范圍將依賴于配置變量列表 dep 這就意味著 被定義的配置變量所對應(yīng)功能的取舍取決于依賴列表所對應(yīng)功能的選擇 以dep bool為例 如果 dep 列表的所有配置變量都取值y 則顯示 prompt 用戶可輸入任意的值給配置變量 symbol 但是只要有一個配置變量的取值為n 則 symbol 被強制成n 不同依賴語句的區(qū)別在于它們由依賴條件所產(chǎn)生的取值范圍不同 5 選擇語句choice prompt word word choice語句首先給出一串選擇列表 供用戶選擇其中一種 比如LinuxforARM支持多種基于ARMcore的CPU Linux使用choice語句提供一個CPU列表 供用戶選擇 choice ARMsystemtype AnakinCONFIG ARCH ANAKIN Archimedes A5000CONFIG ARCH ARCA5K Cirrus CL PS7500FECONFIG ARCH CLPS7500 SA1100 basedCONFIG ARCH SA1100 SharkCONFIG ARCH SHARK RiscPCChoice首先顯示 prompt 然后將 word 分解成前后兩個部分 前部分為對應(yīng)選擇的提示符 后部分是對應(yīng)選擇的配置變量 用戶選擇的配置變量為y 其余的都為n 6 if語句if expr then statement fiif expr then statement else statement fiif語句對配置變量 或配置變量的組合 進行判斷 并作出不同的處理 判斷條件 expr 可以是單個配置變量或字符串 也可以是帶操作符的表達式 操作符有 o a等 7 菜單塊 menublock 語句mainmenu optionnext commentcomment endmenu引入新的菜單 在向內(nèi)核增加新的功能后 需要相應(yīng)的增加新的菜單 并在新菜單下給出此項功能的配置選項 Comment后帶的注釋就是新菜單的名稱 所有歸屬于此菜單的配置選項語句都寫在comment和endmenu之間 8 Source語句source word word 是文件名 source的作用是調(diào)入新的文件 2 默認配置Linux內(nèi)核支持非常多的硬件平臺 對于具體的硬件平臺來說 有些配置是必需的 有些配置卻不是必需的 此外 新增加功能的正常運行往往也需要一定的先決條件 因此 特定硬件平臺能夠正常運行對應(yīng)著一個最小的基本配置 這就是默認配置 Linux內(nèi)核中針對每個ARCH都會有一個默認配置 在向內(nèi)核代碼增加了新的功能后 如果新功能對于這個ARCH是必需的 就要修改此ARCH的默認配置 修改方法如下 在Linux內(nèi)核根目錄下 備份 config文件cparch arm deconfig config修改 configcp configarch arm deconfig恢復 config如果新增的功能適用于許多的ARCH 只要針對具體的ARCH 重復上面的步驟就可以了 3 幫助信息在配置Linux內(nèi)核時 遇到不懂含義的配置選項 可以查看它的幫助 從中可得到選擇的建議 下面介紹如何給一個配置選項增加幫助信息 所有配置選項的幫助信息都在Documentation Configure help中 它的格式為 給出本配置選項的名稱 對應(yīng)配置變量 對應(yīng)配置幫助信息 在幫助信息中 首先簡單描述此功能 其次說明選擇了此功能后會有什么效果 不選擇又有什么效果 最后 不要忘了寫上 如果不清楚 選擇N 或者 Y 給不知所措的用戶以提示 9 2 4配置實例 9 2 4配置實例 對于一個開發(fā)者來說 將自己開發(fā)的內(nèi)核代碼加入到Linux內(nèi)核中 需要有三個步驟 首先確定把自己開發(fā)代碼放入到內(nèi)核的位置 其次 把自己開發(fā)的功能增加到Linux內(nèi)核的配置選項中 使用戶能夠選擇此功能 最后 構(gòu)建子目錄Makefile 根據(jù)用戶的選擇 將相應(yīng)的代碼編譯到最終生成的Linux內(nèi)核中去 下面通過一個簡單的例子 testdriver 說明如何向Linux內(nèi)核中增加新的功能 1 目錄結(jié)構(gòu)testdriver放置在drivers test 目錄下 cddrivers test tree Config in Makefile cpu Makefile cpu c test c test client c test ioctl c test proc c test queue c test Makefile test c 2 配置文件 1 drivers test Config in TESTdriverconfiguration mainmenu optionnext commentcomment TESTDriver bool TESTsupport CONFIG TESTif CONFIG TEST y thentristate TESTuser spaceinterface CONFIG TEST USERbool TESTCPU CONFIG TEST CPUfiEndmenu由于testdriver對于內(nèi)核來說是新的功能 所以首先創(chuàng)建一個菜單TESTDriver 然后 顯示 TESTsupport 等待用戶選擇 接下來判斷用戶是否選擇了TESTDriver 如果是 CONFIG TEST y 則進一步顯示子功能 用戶接口與CPU功能支持 由于用戶接口功能可以被編譯成內(nèi)核模塊 所以這里的詢問語句使用了tristate 因為tristate的取值范圍包括y n和m m就是對應(yīng)著模塊 2 配置文件 2 arch arm config in在文件的最后加入 sourcedrivers test Config in 將TESTDriver子功能的配置納入到Linux內(nèi)核的配置中 3 Makefile 1 drivers test Makefile drivers test Makefile MakefilefortheTEST SUB DIRS MOD SUB DIRS SUB DIRS ALL SUB DIRS SUB DIRS cpuL TARGET test aexport objs test otest client oobj CONFIG TEST test otest queue otest client oobj CONFIG TEST USER test ioctl oobj CONFIG PROC FS test proc osubdir CONFIG TEST CPU cpuinclude TOPDIR Rules makeclean fordirin ALL SUB DIRS domake C dirclean donerm f oa flags d

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論