




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、 動(dòng)態(tài)可加載代碼的優(yōu)點(diǎn)是可以讓內(nèi)核保持很小的尺寸并非常靈活。模塊機(jī)制可以無(wú)需重構(gòu)內(nèi)核并頻繁重新啟動(dòng)來(lái)嘗試運(yùn)行新內(nèi)核代碼。用戶可以根據(jù)自己系統(tǒng)的需要構(gòu)筑自己的私有內(nèi)核。Linux源碼的公開(kāi)更是為改造其內(nèi)核、重建有特殊要求的操作系統(tǒng)提供了可能。 模塊必須能夠找到其需要使用的內(nèi)核資源。例如模塊需要分配內(nèi)存時(shí),要調(diào)用內(nèi)核的內(nèi)存分配例程kmalloc()。但在構(gòu)造模塊時(shí)并不知道kmalloc()在內(nèi)存中何處,這樣內(nèi)核必須在使用這些模塊前修改模塊中對(duì) kmalloc()的引用地址。內(nèi)核在其內(nèi)核符號(hào)表中維護(hù)著一個(gè)內(nèi)核資源鏈表這樣當(dāng)加載模塊時(shí)它能夠解析出模塊 中對(duì)內(nèi)核資源的引用。Linux還允許存在模塊堆棧,
2、它在模塊之間相互調(diào)用時(shí)使用。 例如,因?yàn)閂FAT(VirtuaI File Allocation Table)文件系統(tǒng)是從FAT(File Allocation Table)文件系統(tǒng)中擴(kuò)展而來(lái),VFAT文件系統(tǒng)模塊可能需要FAT文件系統(tǒng)模塊的服務(wù)。某個(gè)模塊對(duì)其他模塊的服務(wù)或資源的需求類似于模塊對(duì)內(nèi)核本身資源或服務(wù)的請(qǐng)求。不過(guò)此時(shí)所請(qǐng)求的服務(wù)是來(lái)自另外一個(gè)事先已加載的模塊。當(dāng)加載模塊時(shí),內(nèi)核就把新近加載模塊輸出的所有資源和符號(hào)添加到內(nèi)核符號(hào)表 (Kernel-Symbol-Table) 中。 在/proc/ksyms.里面的每一個(gè)表項(xiàng)代表著一個(gè)公共的內(nèi)核符號(hào),這就是內(nèi)核符號(hào)表。這些內(nèi)核符號(hào)是可以
3、被LKM引用的。LKM中所存取的每一個(gè)符號(hào)(像函數(shù)名)也會(huì)被列在這個(gè)文件里面。在該文件中可以看到LKM到底可以調(diào)用那些函數(shù)。 當(dāng)試圖卸載某個(gè)模塊時(shí),內(nèi)核需要知道此模塊是否已經(jīng)沒(méi)有被使用,同時(shí)它需要有種方法來(lái)通知此將卸載模塊。 模塊必須能夠在從內(nèi)核種刪除之前釋放其分配的所有系統(tǒng)資源,如內(nèi)核內(nèi)存或中斷。當(dāng)模塊被卸載時(shí),內(nèi)核將從內(nèi)核符號(hào)表中刪除所有與之對(duì)應(yīng)的符號(hào)。 (1) 有可能同時(shí)帶來(lái)與內(nèi)核模塊相關(guān)的性能與內(nèi)存損失??杉虞d模塊的代碼一般較長(zhǎng),且額外的數(shù)據(jù)結(jié)構(gòu)可能會(huì)占據(jù)一些內(nèi)存,對(duì)內(nèi)核資源的間接使用也可能帶來(lái)效率方面的問(wèn)題。對(duì)系統(tǒng)性能和內(nèi)存利用有負(fù)面影響;(1) 有可能同時(shí)帶來(lái)與內(nèi)核模塊相關(guān)的性能與
4、內(nèi)存損失??杉虞d模塊的代碼一般較長(zhǎng),且額外的數(shù)據(jù)結(jié)構(gòu)可能會(huì)占據(jù)一些內(nèi)存,對(duì)內(nèi)核資源的間接使用也可能帶來(lái)效率方面的問(wèn)題。對(duì)系統(tǒng)性能和內(nèi)存利用有負(fù)面影響;(2) 一旦Linux模塊被加載,則和普通內(nèi)核代碼一樣成為內(nèi)核的一部分,具有與其他內(nèi)核代碼相同的權(quán)限與職責(zé)。因此,Linux內(nèi)核模塊也可以象所有內(nèi)核代碼和設(shè)備驅(qū)動(dòng)一樣使內(nèi)核崩潰; (1) 有可能同時(shí)帶來(lái)與內(nèi)核模塊相關(guān)的性能與內(nèi)存損失??杉虞d模塊的代碼一般較長(zhǎng),且額外的數(shù)據(jù)結(jié)構(gòu)可能會(huì)占據(jù)一些內(nèi)存,對(duì)內(nèi)核資源的間接使用也可能帶來(lái)效率方面的問(wèn)題。對(duì)系統(tǒng)性能和內(nèi)存利用有負(fù)面影響;(2) 一旦Linux模塊被加載,則和普通內(nèi)核代碼一樣成為內(nèi)核的一部分,具有
5、與其他內(nèi)核代碼相同的權(quán)限與職責(zé)。因此,Linux內(nèi)核模塊也可以象所有內(nèi)核代碼和設(shè)備驅(qū)動(dòng)一樣使內(nèi)核崩潰; (3) 為了內(nèi)核模塊訪問(wèn)所有內(nèi)核資源,內(nèi)核必須維護(hù)符號(hào)表,并在裝入和卸載模塊時(shí)修改這些符號(hào)表; (1) 有可能同時(shí)帶來(lái)與內(nèi)核模塊相關(guān)的性能與內(nèi)存損失??杉虞d模塊的代碼一般較長(zhǎng),且額外的數(shù)據(jù)結(jié)構(gòu)可能會(huì)占據(jù)一些內(nèi)存,對(duì)內(nèi)核資源的間接使用也可能帶來(lái)效率方面的問(wèn)題。對(duì)系統(tǒng)性能和內(nèi)存利用有負(fù)面影響;(2) 一旦Linux模塊被加載,則和普通內(nèi)核代碼一樣成為內(nèi)核的一部分,具有與其他內(nèi)核代碼相同的權(quán)限與職責(zé)。因此,Linux內(nèi)核模塊也可以象所有內(nèi)核代碼和設(shè)備驅(qū)動(dòng)一樣使內(nèi)核崩潰; (3) 為了內(nèi)核模塊訪問(wèn)所
6、有內(nèi)核資源,內(nèi)核必須維護(hù)符號(hào)表,并在裝入和卸載模塊時(shí)修改這些符號(hào)表; (4) 有些模塊要求利用其他模塊的功能,因此,內(nèi)核要維護(hù)模塊之間的依賴性。(5) 內(nèi)核必須能夠在卸載模塊時(shí)通知模塊,并且要釋放分配給模塊的內(nèi)存和中斷等資源;(6) 內(nèi)核版本和模塊版本的不兼容,也可能導(dǎo)致系統(tǒng)崩潰,因此,嚴(yán)格的版本檢查是必需的。 當(dāng)內(nèi)核發(fā)現(xiàn)有必要加載某個(gè)模塊時(shí),如用戶安裝了內(nèi)核中不存在的文件系統(tǒng)時(shí),內(nèi)核將請(qǐng)求內(nèi)核后臺(tái)進(jìn)程(kerneld)準(zhǔn)備加載適當(dāng)?shù)哪K。這個(gè)內(nèi)核后臺(tái)進(jìn)程僅僅是一個(gè)帶有超級(jí)用戶權(quán)限的普通用戶進(jìn)程。當(dāng)系統(tǒng)啟動(dòng)時(shí)它也被啟動(dòng)并為內(nèi)核打開(kāi)了一個(gè)進(jìn)程間通訊(IPC)通道。內(nèi)核可以利用該通道向Kernel
7、d進(jìn)程發(fā)送任務(wù)的執(zhí)行請(qǐng)求。Kerneld進(jìn)程的主要功能是加載和卸載模塊,另外,該進(jìn)程也負(fù)責(zé)其他一些任務(wù),例如打開(kāi)和關(guān)閉 PPP 鏈接等。kerneld自身并不執(zhí)行這些任務(wù),它通過(guò)某些程序如insmod來(lái)做此工作。因此,該進(jìn)程實(shí)際是代表內(nèi)核進(jìn)行調(diào)度的代理。 執(zhí)行 insmod 命令時(shí),必須指定要加載模塊的位置;對(duì)需求加載的內(nèi)核模塊,通常保存在 /lib/modules/kernel-version。和系統(tǒng)的其他程序一樣,內(nèi)核模塊實(shí)際是經(jīng)連接的目標(biāo)文件,但模塊是可重定位的,也就是說(shuō),為了讓裝入的模塊和已有的內(nèi)核組件之間可以互相訪問(wèn),模塊不能連接為從特定地址執(zhí)行的映像文件。模塊可以是 a.out 或
8、 elf 格式的目標(biāo)文件。insmod 利用一個(gè)特權(quán)系統(tǒng)調(diào)用,可找到內(nèi)核的導(dǎo)出符號(hào)表,符號(hào)成對(duì)出現(xiàn),一個(gè)是符號(hào)名稱,另外一個(gè)是符號(hào)的值,例如符號(hào)的地址。內(nèi)核維護(hù)一個(gè)由 module_list 指針指向的 module 鏈表,其中第一個(gè) module 數(shù)據(jù)結(jié)構(gòu)保存有內(nèi)核的導(dǎo)出符號(hào)表(見(jiàn)圖(見(jiàn)圖 9.1)。并不是所有的內(nèi)核符號(hào)均在符號(hào)表中導(dǎo)出,而只有一些特殊的符號(hào)才被添加到符號(hào)表中。例如,“request_irq”是一個(gè)導(dǎo)出符號(hào),它是一個(gè)內(nèi)核例程,可由驅(qū)動(dòng)程序申請(qǐng)控制某個(gè)特定的系統(tǒng)中斷。利用 ksyms 命令或查看 /proc/ksyms 文件內(nèi)容,可非常方便地看到所有的內(nèi)核導(dǎo)出符號(hào)及其符號(hào)值。利
9、用 ksyms 命令,不僅可以看到內(nèi)核的所有符號(hào),也可以看到只由以加載模塊導(dǎo)出的符號(hào)。insmod 命令將模塊讀到它本身的虛擬內(nèi)存中,然后利用內(nèi)核導(dǎo)出的符號(hào)表,修正尚未解析的對(duì)內(nèi)核例程的引用。這種修正實(shí)際是對(duì)模塊在內(nèi)存中的映像進(jìn)行修正,insmod 將符號(hào)的地址寫(xiě)入模塊中適當(dāng)?shù)奈恢枚鴮?shí)現(xiàn)修正。圖 9.1 裝入 VFAT 和 FAT 之后的內(nèi)核模塊表 insmod 命令修正模塊對(duì)內(nèi)核符號(hào)的引用之后,再次利用特權(quán)系統(tǒng)調(diào)用請(qǐng)求內(nèi)核分配足夠的物理內(nèi)存空間保存新的模塊。內(nèi)核將分配新的 module 數(shù)據(jù)結(jié)構(gòu)以及足夠的內(nèi)核內(nèi)存,并將新模塊添加在內(nèi)核模塊表的末尾。新的內(nèi)核模塊標(biāo)記為Uninitialized
10、(未初始化)。圖 9.1是裝入 VFAT 和 FAT 模塊之后的內(nèi)核模塊表。圖中并沒(méi)有表示出第一個(gè)模塊,它實(shí)際是一個(gè)偽模塊,僅僅用來(lái)保存內(nèi)核的導(dǎo)出符號(hào)表。利用 lsmod 命令可列出所有已加載的內(nèi)核模塊以及它們的內(nèi)在依賴性。內(nèi)核為新模塊分配的內(nèi)核內(nèi)存映射到 insmod 進(jìn)程的地址空間中,這樣,insmod 就可以將模塊復(fù)制到新分配的內(nèi)存中。insmod 還對(duì)模塊進(jìn)行重新定位,經(jīng)重定位之后,新的模塊就可以從新分配的內(nèi)核地址開(kāi)始運(yùn)行了。顯然,模塊不能期望自己能夠在不同的 Linux 系統(tǒng),或前后兩次裝入時(shí)被加載到相同地址,重定位操作可通過(guò)對(duì)模塊映像中適當(dāng)?shù)牡刂愤M(jìn)行修正而解決這一問(wèn)題。 新的模塊也
11、要向內(nèi)核導(dǎo)出符號(hào),由 insmod 建立相應(yīng)的符號(hào)表。每個(gè)內(nèi)核模塊必須包含模塊的初始化和清除例程,這些例程作為每個(gè)模塊均具備的例程而不被導(dǎo)出,但 insmod 必須知道它們的地址,并將地址傳遞給內(nèi)核。insmod 同樣利用特權(quán)系統(tǒng)調(diào)用將模塊的初始化和清除例程地址傳遞給內(nèi)核。 新的模塊添加到內(nèi)核之后,它必須更新內(nèi)核符號(hào)集并修改使用新模塊的模塊。由其他模塊依賴的模塊必須在自身符號(hào)表的末尾維護(hù)一個(gè)引用表,并指向其他模塊的 module 結(jié)構(gòu)。例如,圖 9.1 表明 VFAT 文件系統(tǒng)模塊依賴于 FAT 文件系統(tǒng)模塊,因此,F(xiàn)AT 模塊包含一個(gè)對(duì) VFAT 模塊的引用,該引用在裝入 VFAT 模塊時(shí)添
12、加。 內(nèi)核成功調(diào)用模塊的初始化例程之后繼續(xù)模塊的安裝,最后,模塊狀態(tài)被設(shè)置為 Running(運(yùn)行)。模塊的清除例程保存在 module 數(shù)據(jù)結(jié)構(gòu)中,在卸載模塊時(shí)由內(nèi)核調(diào)用。 如果內(nèi)核的其他部分依賴于裝入的模塊時(shí),該模塊不能卸載。例如,如果掛裝了 FAT 文件系統(tǒng),則不能卸載已裝入的 FAT 文件系統(tǒng)模塊。lsmod 命令的輸出會(huì)顯示已安裝模塊的使用計(jì)數(shù),例如: Module:#pages: Used by: msdos 5 1 vfat 4 1 (autoclean) fat 6 2 (autoclean) 使用計(jì)數(shù)就是依賴于該模塊的內(nèi)核實(shí)體個(gè)數(shù)。模塊的使用計(jì)數(shù)保存在模塊映像的第一個(gè)長(zhǎng)整型中
13、。但是,這一長(zhǎng)整型中還包含有 AUTOCLEAN 和 VISITED 標(biāo)志。這兩個(gè)標(biāo)志均由需求加載的模塊使用。具有 AUTOCLEAN 標(biāo)志的模塊是系統(tǒng)認(rèn)為可以自動(dòng)卸載的模塊。具有 VISITED 標(biāo)志的模塊表明正由其他內(nèi)核組件使用,當(dāng)任何其他內(nèi)核組件使用該模塊是設(shè)置該標(biāo)志。當(dāng) kerneld 請(qǐng)求系統(tǒng)移走不使用的需求加載模塊時(shí),系統(tǒng)首先尋找可以移走的模塊,但系統(tǒng)只查看標(biāo)記為 AUTOCLEAN,并且狀態(tài)處于 RUNNING 的模塊。如果上述模塊的 VISITED 標(biāo)志被清除,則系統(tǒng)將卸載該模塊,否則系統(tǒng)會(huì)清除 VISITED 標(biāo)志并查看下一個(gè)模塊。 假定某個(gè)模塊是可卸載的,則系統(tǒng)調(diào)用其清除例
14、程釋放分配該模塊的內(nèi)核資源。相應(yīng)的 module 數(shù)據(jù)結(jié)構(gòu)被標(biāo)志為 DELETED 并從內(nèi)核模塊鏈表中斷開(kāi)。所有由該模塊依賴的模塊,系統(tǒng)會(huì)修改它們的引用表以便取消依賴性。最后,系統(tǒng)釋放模塊的內(nèi)核內(nèi)存。 在Linux里,除了直接修改系統(tǒng)核心的源代碼,把設(shè)備驅(qū)動(dòng)程序加進(jìn)核心里以外,還可以把設(shè)備驅(qū)動(dòng)程序作為可加載的模塊,由系統(tǒng)管理員動(dòng)態(tài)地加載它,使之成為核心的一部分。也可以由系統(tǒng)管理員把已加載地模塊動(dòng)態(tài)地卸載下來(lái)。 Linux的模塊可以用C語(yǔ)言編寫(xiě),用gcc編譯成目標(biāo)文件(不進(jìn)行鏈接,作為*.o文件存在),為此需要在gcc命令行里加上-c的參數(shù)。在編譯時(shí),還應(yīng)該在gcc的命令行里加上這樣的參數(shù):-D
15、_KERNEL_ -DMODULE。由于在不鏈接時(shí),gcc只允許一個(gè)輸入文件,因此一個(gè)模塊的所有部分都必須在一個(gè)文件里實(shí)現(xiàn)。 編譯好的模塊*.o放/lib/modules/xxxx/misc下(xxxx表示核心版本,如在核心版本為2.0.30時(shí)應(yīng)該為/lib/modules/2.0.30/misc),然后用depmod -a使此模塊成為可加載模塊。模塊用insmod命令加載,用rmmod命令來(lái)卸載,并可以用lsmod命令來(lái)查看所有已加載的模塊的狀態(tài)。 利用 insmod 命令可手工裝入內(nèi)核模塊;利用 lsmod 可查看當(dāng)前裝入的內(nèi)核模塊以及需求加載模塊的使用計(jì)數(shù)及標(biāo)志信息;利用 rmmod 則
16、可以卸載指定的模塊。 編寫(xiě)模塊程序的時(shí)候,必須提供兩個(gè)函數(shù),一個(gè)是int init_module(void),供insmod在加載此模塊的時(shí)候自動(dòng)調(diào)用,負(fù)責(zé)進(jìn)行設(shè)備驅(qū)動(dòng)程序的初始化工作。init_module返回0以表示初始化成功,返回負(fù)數(shù)表示失敗。另一個(gè)函數(shù)是void cleanup_module (void),在模塊被卸載時(shí)調(diào)用,負(fù)責(zé)進(jìn)行設(shè)備驅(qū)動(dòng)程序的清除工作。 在成功的向系統(tǒng)注冊(cè)了設(shè)備驅(qū)動(dòng)程序后(調(diào)用register_chrdev成功后),就可以用mknod命令來(lái)把設(shè)備映射為一個(gè)特別文件,其它程序使用這個(gè)設(shè)備的時(shí)候,只要對(duì)此特別文件進(jìn)行操作就行了。 隨著 Linux 操作系統(tǒng)的廣泛應(yīng)用,
17、特別是 Linux 在嵌入式領(lǐng)域的發(fā)展,越來(lái)越多的人開(kāi)始投身到 Linux 內(nèi)核級(jí)的開(kāi)發(fā)中。面對(duì)日益龐大的 Linux 內(nèi)核源代碼,開(kāi)發(fā)者在完成自己的內(nèi)核代碼后,都將面臨著同樣的問(wèn)題,即如何將源代碼融入到 Linux 內(nèi)核中,增加相應(yīng)的 Linux 配置選項(xiàng),并最終被編譯進(jìn) Linux 內(nèi)核。這就需要了解 Linux 的內(nèi)核配置系統(tǒng)。 Linux 內(nèi)核是由分布在全球的 Linux 愛(ài)好者共同開(kāi)發(fā)的,Linux 內(nèi)核每天都面臨著許多新的變化。但是,Linux 內(nèi)核的組織并沒(méi)有出現(xiàn)混亂的現(xiàn)象,反而顯得非常的簡(jiǎn)潔,而且具有很好的擴(kuò)展性,開(kāi)發(fā)人員可以很方便的向 Linux 內(nèi)核中增加新的內(nèi)容。原因之一
18、就是 Linux 采用了模塊化的內(nèi)核配置系統(tǒng),從而保證了內(nèi)核的擴(kuò)展性。Linux內(nèi)核的配置系統(tǒng)由三個(gè)部分組成:內(nèi)核的配置系統(tǒng)由三個(gè)部分組成:(1)Makefile:分布在 Linux 內(nèi)核源代碼中的Makefile 定義 Linux 內(nèi)核的編譯規(guī)則; (2)配置文件(config.in):給用戶提供配置選擇的功能; (3)配置工具:包括配置命令解釋器(對(duì)配置腳本中使用的配置命令進(jìn)行解釋)和配置用戶界面(提供基于字符界面、基于 Ncurses 圖形界面以及基于 Xwindows 圖形界面的用戶配置界面,各自對(duì)應(yīng)于 Make config、Make menuconfig 和Make xconfig
19、)。 這些配置工具都是使用腳本語(yǔ)言,如 Tcl/TK、Perl 編寫(xiě)的(也包含一些用 C 編寫(xiě)的代碼)。除非是配置系統(tǒng)的維護(hù)者,一般的內(nèi)核開(kāi)發(fā)者無(wú)須了解配置系統(tǒng)的原理,只需要知道如何使用配置系統(tǒng),如何編寫(xiě) Makefile 和配置文件就可以。所以,本節(jié)只對(duì) Makefile 和配置文件進(jìn)行討論。凡是涉及到與具體 CPU 體系結(jié)構(gòu)相關(guān)的內(nèi)容,都以 ARM 為例,這樣不僅可以將討論的問(wèn)題明確化,而且對(duì)內(nèi)容本身不產(chǎn)生影響。 由于 Linux 內(nèi)核源代碼是按照樹(shù)形結(jié)構(gòu)組織的,所以 Makefile 也被分布在目錄樹(shù)中。Linux 內(nèi)核中的 Makefile 以及與 Makefile 直接相關(guān)的文件有:
20、 Makefile:頂層 Makefile,是整個(gè)內(nèi)核配置、編譯的總體控制文件。 .config:內(nèi)核配置文件,包含由用戶選擇的配置選項(xiàng),用來(lái)存放內(nèi)核配置后的結(jié)果(如 make config)。 arch/*/Makefile:位于各種 CPU 體系目錄下的 Makefile,如 arch/arm/Makefile,是針對(duì)特定平臺(tái)的 Makefile。 各個(gè)子目錄下的 Makefile:比如 drivers/Makefile,負(fù)責(zé)所在子目錄下源代碼的管理。 Rules.make:規(guī)則文件,被所有的 Makefile 使用。 用戶通過(guò) make config 配置后,產(chǎn)生了 .config。頂層
21、 Makefile 讀入 .config 中的配置選擇。頂層 Makefile 有兩個(gè)主要的任務(wù):產(chǎn)生 vmlinux 文件和內(nèi)核模塊(module)。為了達(dá)到此目的,頂層 Makefile 遞歸的進(jìn)入到內(nèi)核的各個(gè)子目錄中,分別調(diào)用位于這些子目錄中的 Makefile。至于到底進(jìn)入哪些子目錄,取決于內(nèi)核的配置。在頂層 Makefile 中,有一句:include arch/$(ARCH)/Makefile,包含了特定 CPU 體系結(jié)構(gòu)下的 Makefile,這個(gè) Makefile 中包含了平臺(tái)相關(guān)的信息。 位于各個(gè)子目錄下的 Makefile 同樣也根據(jù) .config 給出的配置信息,構(gòu)造出
22、當(dāng)前配置下需要的源文件列表,并在文件的最后有 include $(TOPDIR)/Rules.make。 Rules.make 文件起著非常重要的作用,它定義了所有 Makefile 共用的編譯規(guī)則。比如,如果需要將本目錄下所有的 c 程序編譯成匯編代碼,需要在 Makefile 中有以下的編譯規(guī)則: %.s: %.c $(CC) $(CFLAGS) -S $ -o $ 有很多子目錄下都有同樣的要求,就需要在各自的 Makefile 中包含此編譯規(guī)則,這會(huì)比較麻煩。而 Linux 內(nèi)核中則把此類的編譯規(guī)則統(tǒng)一放置到 Rules.make 中,并在各自的 Makefile 中包含進(jìn)了 Rules
23、.make(include Rules.make),這樣就避免了在多個(gè) Makefile 中重復(fù)同樣的規(guī)則。對(duì)于上面的例子,在 Rules.make 中對(duì)應(yīng)的規(guī)則為: %.s: %.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F) $(CFLAGS_$) -S $ -o $1.Makefile 中的變量 頂層 Makefile 定義并向環(huán)境中輸出了許多變量,為各個(gè)子目錄下的 Makefile 傳遞一些信息。有些變量,比如 SUBDIRS,不僅在頂層 Makefile 中定義并且賦初值,而且在 arch/*/Makefile 還作了擴(kuò)充。 常用的變
24、量有以下幾類:(1) 版本信息版本信息版本信息有:VERSION、PATCHLEVEL、SUBLEVEL、 EXTRAVERSION和KERNELRELEASE。版本信息定義了當(dāng)前內(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):體系結(jié)構(gòu):ARCH在頂層 Makefile 的開(kāi)頭,用 ARCH 定義目標(biāo) CPU 的體系結(jié)構(gòu),比如 ARCH:=arm 等。許多子目錄的 Makefile 中,要根據(jù) ARCH 的定義選擇編譯
25、源文件的列表。(3) 路徑信息:路徑信息:TOPDIR和和SUBDIRSTOPDIR 定義了 Linux 內(nèi)核源代碼所在的根目錄。例如,各個(gè)子目錄下的 Makefile 通過(guò) $(TOPDIR)/Rules.make 就可以找到 Rules.make 的位置。SUBDIRS 定義了一個(gè)目錄列表,在編譯內(nèi)核或模塊時(shí),頂層 Makefile 就是根據(jù) SUBDIRS 來(lái)決定進(jìn)入哪些子目錄。SUBDIRS 的值取決于內(nèi)核的配置,在頂層 Makefile 中 SUBDIRS 賦值為 kernel drivers mm fs net ipc lib;根據(jù)內(nèi)核的配置情況,在 arch/*/Makefile
26、 中擴(kuò)充了 SUBDIRS 的值。 (4) 內(nèi)核組成信息:HEAD、CORE_FILES、NETWORKS、DRIVERS、LIBSLinux 內(nèi)核文件 vmlinux 是由以下規(guī)則產(chǎn)生的: vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o -start-group $(CORE_FILES) $(DRIVERS) $(NETWORKS) $(LIBS) -end-group -o vmlinux 可以看出
27、,vmlinux 是由 HEAD、main.o、version.o、CORE_FILES、DRIVERS、NETWORKS 和 LIBS 組成的。這些變量(如 HEAD)都是用來(lái)定義連接生成 vmlinux 的目標(biāo)文件和庫(kù)文件列表。其中,HEAD在arch/*/Makefile 中定義,用來(lái)確定被最先鏈接進(jìn) vmlinux 的文件列表。例如,對(duì)于 ARM 系列的 CPU,HEAD 定義為: HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o 表明 head-$(PROCESSOR).o 和 init_t
28、ask.o 需要最先被鏈接到 vmlinux 中。PROCESSOR 為 armv 或 armo,取決于目標(biāo) CPU。 CORE_FILES,NETWORK,DRIVERS 和 LIBS 在頂層 Makefile 中定義,并且由 arch/*/Makefile 根據(jù)需要進(jìn)行擴(kuò)充。 CORE_FILES 對(duì)應(yīng)著內(nèi)核的核心文件,有 kernel/kernel.o,mm/mm.o,fs/fs.o,ipc/ipc.o,可以看出,這些是組成內(nèi)核最為重要的文件。同時(shí),arch/arm/Makefile 對(duì) CORE_FILES 進(jìn)行了擴(kuò)充:# arch/arm/Makefile # If we have
29、a machine-specific directory, then include it in the build.MACHDIR := arch/arm/mach-$(MACHINE)ifeq ($(MACHDIR),$(wildcard $(MACHDIR)SUBDIRS += $(MACHDIR)CORE_FILES := $(MACHDIR)/$(MACHINE).o $(CORE_FILES)endif HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.oSUBDIRS += arch/arm
30、/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpeCORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)LIBS := arch/arm/lib/lib.a $(LIBS)(5) 編譯信息:CPP, CC, AS, LD, AR,CFLAGS,LINKFLAGS 在 Rules.make 中定義的是編譯的通用規(guī)則,具體到特定的場(chǎng)合,需要明確給出編譯環(huán)境,編譯環(huán)境就是在以上的變量中定義的。針對(duì)交叉編譯的要求,定義了 CROSS_COMPILE。如:CROSS_COMPI
31、LE = arm-linux-CC = $(CROSS_COMPILE)gccLD = $(CROSS_COMPILE)ld. CROSS_COMPILE 定義了交叉編譯器前綴 arm-linux-,表明所有的交叉編譯工具都是以 arm-linux- 開(kāi)頭的,所以在各個(gè)交叉編譯器工具之前,都加入了 $(CROSS_COMPILE),以組成一個(gè)完整的交叉編譯工具文件名,比如 arm-linux-gcc。 CFLAGS 定義了傳遞給 C 編譯器的參數(shù)。 LINKFLAGS 是鏈接生成 vmlinux 時(shí),由鏈接器使用的參數(shù)。 LINKFLAGS 在 arm/*/Makefile 中定義,如: #
32、arch/arm/Makefile LINKFLAGS :=-p -X -T arch/arm/vmlinux.lds(6) 配置變量CONFIG_*.config 文件中有許多的配置變量等式,用來(lái)說(shuō)明用戶配置的結(jié)果。例如 CONFIG_MODULES=y 表明用戶選擇了 Linux 內(nèi)核的模塊功能。.config 被頂層 Makefile 包含后,就形成許多的配置變量,每個(gè)配置變量具有確定的值:y 表示本編譯選項(xiàng)對(duì)應(yīng)的內(nèi)核代碼被靜態(tài)編譯進(jìn) Linux 內(nèi)核;m 表示本編譯選項(xiàng)對(duì)應(yīng)的內(nèi)核代碼被編譯成模塊;n 表示不選擇此編譯選項(xiàng);如果根本就沒(méi)有選擇,那么配置變量的值為空。 2. Rules.m
33、ake 變量變量 Rules.make 是編譯規(guī)則文件,所有的 Makefile 中都會(huì)包括 Rules.make。Rules.make 文件定義了許多變量,最為重要是那些編譯、鏈接列表變量。 O_OBJS,L_OBJS,OX_OBJS,LX_OBJS:本目錄下需要編譯進(jìn) Linux 內(nèi)核 vmlinux 的目標(biāo)文件列表,其中 OX_OBJS 和 LX_OBJS 中的 X 表明目標(biāo)文件使用了 EXPORT_SYMBOL 輸出符號(hào)。 M_OBJS,MX_OBJS:本目錄下需要被編譯成可裝載模塊的目標(biāo)文件列表。同樣,MX_OBJS 中的 X 表明目標(biāo)文件使用了 EXPORT_SYMBOL 輸出符號(hào)
34、。 O_TARGET,L_TARGET:每個(gè)子目錄下都有一個(gè) O_TARGET 或 L_TARGET,Rules.make 首先從源代碼編譯生成 O_OBJS 和 OX_OBJS 中所有的目標(biāo)文件,然后使用 $(LD) -r 把它們鏈接成一個(gè) O_TARGET 或 L_TARGET。O_TARGET 以 .o 結(jié)尾,而 L_TARGET 以 .a 結(jié)尾。 子目錄Makefile 用來(lái)控制本級(jí)目錄以下源代碼的編譯規(guī)則。下面通過(guò)一個(gè)例子來(lái)講解子目錄 Makefile 的組成: # Makefile for the linux kernel.# All of the (potential) obje
35、cts that export symbols.# This list comes from grep -l EXPORT_SYMBOL *.hc. export-objs:= tc.o # Object file lists. obj-y:=obj-m:=obj-n:=obj-:= obj-$(CONFIG_TC) += tc.oobj-$(CONFIG_ZS) += zs.oobj-$(CONFIG_VT) += lk201.o lk201-map.o lk201-remap.o # Files that are both resident and modular: remove from
36、 modular. obj-m:= $(filter-out $(obj-y), $(obj-m) # Translate to Rules.make lists.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
37、-m) include $(TOPDIR)/Rules.make(1) 注釋對(duì) Makefile 的說(shuō)明和解釋,由#開(kāi)始。(2) 編譯目標(biāo)定義 類似于 obj-$(CONFIG_TC) += tc.o 的語(yǔ)句是用來(lái)定義編譯的目標(biāo),是子目錄 Makefile 中最重要的部分。編譯目標(biāo)定義那些在本子目錄下,需要編譯到 Linux 內(nèi)核中的目標(biāo)文件列表。為了只在用戶選擇了此功能后才編譯,所有的目標(biāo)定義都融合了對(duì)配置變量的判斷。 前面說(shuō)過(guò),每個(gè)配置變量取值范圍是:y,n,m 和空,obj-$(CONFIG_TC) 分別對(duì)應(yīng)著 obj-y,obj-n,obj-m,obj-。如果 CONFIG_TC 配置
38、為 y,那么 tc.o 就進(jìn)入了 obj-y 列表。obj-y 為包含到 Linux 內(nèi)核 vmlinux 中的目標(biāo)文件列表;obj-m 為編譯成模塊的目標(biāo)文件列表;obj-n 和 obj- 中的文件列表被忽略。配置系統(tǒng)就根據(jù)這些列表的屬性進(jìn)行編譯和鏈接。export-objs 中的目標(biāo)文件都使用了 EXPORT_SYMBOL() 定義了公共的符號(hào),以便可裝載模塊使用。在 tc.c 文件的最后部分,有 “EXPORT_SYMBOL(search_tc_card);”,表明 tc.o 有符號(hào)輸出。 這里需要指出的是,對(duì)于編譯目標(biāo)的定義,存在著兩種格式,分別是老式定義和新式定義。老式定義就是前面
39、Rules.make 使用的那些變量,新式定義就是 obj-y,obj-m,obj-n 和 obj-。Linux 內(nèi)核推薦使用新式定義,不過(guò)由于 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_
40、OBJS 的生成方式:在 obj-y 的列表中過(guò)濾掉 export-objs(tc.o),然后排序并去除重復(fù)的文件名。這里使用到了 GNU Make 的一些特殊功能,具體的含義可參考 Make 的文檔(info make)。(4) include $(TOPDIR)/Rules.make在 Linux 內(nèi)核中,配置命令有多種方式:配置命令解釋腳本Make config, make oldconfigscripts/ConfigureMake menuconfigscripts/MenuconfigMake xconfigscripts/tkparse以字符界面配置(make config)為例
41、,頂層 Makefile 調(diào)用 scripts/Configure, 按照 arch/arm/config.in 來(lái)進(jìn)行配置。命令執(zhí)行完后產(chǎn)生文件 .config,其中保存著配置信息。下一次再做 make config 將產(chǎn)生新的 .config 文件,原 .config 被改名為 .config.old。1. 配置語(yǔ)言配置語(yǔ)言(1) 頂層菜單mainmenu_name /prompt/ /prompt/ 是用或包圍的字符串,與的區(qū)別是中可使用$引用變量的值。mainmenu_name 設(shè)置最高層菜單的名字,它只在 make xconfig 時(shí)才會(huì)顯示。(2) 詢問(wèn)語(yǔ)句 bool /promp
42、t/ /symbol/hex /prompt/ /symbol/ /word/int /prompt/ /symbol/ /word/string /prompt/ /symbol/ /word/tristate/prompt/ /symbol/ 詢問(wèn)語(yǔ)句首先顯示一串提示符 /prompt/,等待用戶輸入,并把輸入的結(jié)果賦給 /symbol/ 所代表的配置變量。不同的詢問(wèn)語(yǔ)句的區(qū)別在于它們接受的輸入數(shù)據(jù)類型不同,比如 bool 接受布爾類型( y 或 n ),hex 接受 16 進(jìn)制數(shù)據(jù)。有些詢問(wèn)語(yǔ)句還有第三個(gè)參數(shù) /word/,用來(lái)給出默認(rèn)值。 (3) 定義語(yǔ)句 define_bool /s
43、ymbol/ /word/define_hex /symbol/ /word/define_int /symbol/ /word/define_string /symbol/ /word/define_tristate /symbol/ /word/不同于詢問(wèn)語(yǔ)句等待用戶輸入,定義語(yǔ)句顯式的給配置變量 /symbol/ 賦值 /word/。 (3) 定義語(yǔ)句 define_bool /symbol/ /word/define_hex /symbol/ /word/define_int /symbol/ /word/define_string /symbol/ /word/define_tris
44、tate /symbol/ /word/ 不同于詢問(wèn)語(yǔ)句等待用戶輸入,定義語(yǔ)句顯式的給配置變量 /symbol/ 賦值 /word/。 (4) 依賴語(yǔ)句 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/ /
45、dep/ . 與詢問(wèn)語(yǔ)句類似,依賴語(yǔ)句也是定義新的配置變量。不同的是,配置變量/symbol/的取值范圍將依賴于配置變量列表/dep/ 。這就意味著:被定義的配置變量所對(duì)應(yīng)功能的取舍取決于依賴列表所對(duì)應(yīng)功能的選擇。以dep_bool為例,如果/dep/ 列表的所有配置變量都取值y,則顯示/prompt/,用戶可輸入任意的值給配置變量/symbol/,但是只要有一個(gè)配置變量的取值為n,則/symbol/被強(qiáng)制成n。 不同依賴語(yǔ)句的區(qū)別在于它們由依賴條件所產(chǎn)生的取值范圍不同。 (5) 選擇語(yǔ)句 choice /prompt/ /word/ /word/ choice 語(yǔ)句首先給出一串選擇列表,供用
46、戶選擇其中一種。比如 Linux for ARM 支持多種基于 ARM core 的 CPU,Linux 使用 choice 語(yǔ)句提供一個(gè) CPU 列表,供用戶選擇: choice ARM system type Anakin CONFIG_ARCH_ANAKIN Archimedes/A5000 CONFIG_ARCH_ARCA5K Cirrus-CL-PS7500FE CONFIG_ARCH_CLPS7500 SA1100-based CONFIG_ARCH_SA1100 Shark CONFIG_ARCH_SHARK RiscPC Choice 首先顯示 /prompt/,然后將 /wo
47、rd/ 分解成前后兩個(gè)部分,前部分為對(duì)應(yīng)選擇的提示符,后部分是對(duì)應(yīng)選擇的配置變量。用戶選擇的配置變量為 y,其余的都為 n。 (6) if語(yǔ)句if /expr/ ; then /statement/ .fi if /expr/ ; then /statement/ .else /statement/ .fi if 語(yǔ)句對(duì)配置變量(或配置變量的組合)進(jìn)行判斷,并作出不同的處理。判斷條件 /expr/ 可以是單個(gè)配置變量或字符串,也可以是帶操作符的表達(dá)式。操作符有:=,!=,-o,-a 等。 (7) 菜單塊(menu block)語(yǔ)句 mainmenu_option next_comment co
48、mment . endmenu 引入新的菜單。在向內(nèi)核增加新的功能后,需要相應(yīng)的增加新的菜單,并在新菜單下給出此項(xiàng)功能的配置選項(xiàng)。Comment 后帶的注釋就是新菜單的名稱。所有歸屬于此菜單的配置選項(xiàng)語(yǔ)句都寫(xiě)在 comment 和 endmenu 之間。 (8) Source 語(yǔ)句 source /word/word/ 是文件名,source 的作用是調(diào)入新的文件。 2. 默認(rèn)配置默認(rèn)配置 Linux 內(nèi)核支持非常多的硬件平臺(tái),對(duì)于具體的硬件平臺(tái)來(lái)說(shuō),有些配置是必需的,有些配置卻不是必需的。此外,新增加功能的正常運(yùn)行往往也需要一定的先決條件。因此,特定硬件平臺(tái)能夠正常運(yùn)行對(duì)應(yīng)著一個(gè)最小的基本配
49、置,這就是默認(rèn)配置。 Linux 內(nèi)核中針對(duì)每個(gè) ARCH 都會(huì)有一個(gè)默認(rèn)配置。在向內(nèi)核代碼增加了新的功能后,如果新功能對(duì)于這個(gè) ARCH 是必需的,就要修改此 ARCH 的默認(rèn)配置。修改方法如下(在 Linux 內(nèi)核根目錄下): 備份 .config 文件 cp arch/arm/deconfig .config 修改 .config cp .config arch/arm/deconfig 恢復(fù) .config 如果新增的功能適用于許多的 ARCH,只要針對(duì)具體的 ARCH,重復(fù)上面的步驟就可以了。3. 幫助信息幫助信息 在配置 Linux 內(nèi)核時(shí),遇到不懂含義的配置選項(xiàng),可以查看它的幫助
50、,從中可得到選擇的建議。下面介紹如何給一個(gè)配置選項(xiàng)增加幫助信息。 所有配置選項(xiàng)的幫助信息都在 Documentation/ Configure.help 中,它的格式為: 給出本配置選項(xiàng)的名稱, 對(duì)應(yīng)配置變量, 對(duì)應(yīng)配置幫助信息。在幫助信息中,首先簡(jiǎn)單描述此功能,其次說(shuō)明選擇了此功能后會(huì)有什么效果,不選擇又有什么效果,最后,不要忘了寫(xiě)上如果不清楚,選擇 N(或者)Y,給不知所措的用戶以提示。 1. 目錄結(jié)構(gòu)test driver 放置在 drivers/test/ 目錄下: $cd drivers/test $tree . |- Config.in |- Makefile |- cpu | |
51、- Makefile | - cpu.c |- test.c |- test_client.c |- test_ioctl.c |- test_proc.c |- test_queue.c - test |- Makefile - test.c2. 配置文件配置文件(1) drivers/test/Config.in # TEST driver configuration#mainmenu_option next_commentcomment TEST Driver bool TEST support CONFIG_TESTif $CONFIG_TEST = y ; then tristate
52、 TEST user-space interface CONFIG_TEST_USER bool TEST CPU CONFIG_TEST_CPUfi Endmenu 由于 test driver 對(duì)于內(nèi)核來(lái)說(shuō)是新的功能,所以首先創(chuàng)建一個(gè)菜單 TEST Driver。然后,顯示 TEST support,等待用戶選擇;接下來(lái)判斷用戶是否選擇了 TEST Driver,如果是(CONFIG_TEST=y),則進(jìn)一步顯示子功能:用戶接口與 CPU 功能支持;由于用戶接口功能可以被編譯成內(nèi)核模塊,所以這里的詢問(wèn)語(yǔ)句使用了 tristate(因?yàn)?tristate 的取值范圍包括 y、n 和 m,m 就是對(duì)應(yīng)著模塊)。 2. 配置文件配置文件(2) arch/arm/config.in 在文件的最后加入:source drivers/test/Config.in,將 TEST
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 學(xué)生評(píng)教與反饋實(shí)施方案計(jì)劃
- 靜脈治療報(bào)告
- 統(tǒng)編版小學(xué)語(yǔ)文二年級(jí)下冊(cè)《語(yǔ)文園地三》精美課件
- 第四單元 《平行四邊形的認(rèn)識(shí)》教學(xué)設(shè)計(jì)-2024-2025學(xué)年四年級(jí)數(shù)學(xué)上冊(cè)青島版(五四學(xué)制)
- 養(yǎng)老床位建設(shè)服務(wù)方案(技術(shù)方案)
- 老年骨折手術(shù)護(hù)理
- 放射科護(hù)理相關(guān)知識(shí)課件
- 培訓(xùn)課件知識(shí)產(chǎn)權(quán)保護(hù)
- 2025年湛江道路客貨運(yùn)輸從業(yè)資格證模擬考試下載
- 2025年上海貨運(yùn)從業(yè)資格證模擬試題答案大全
- GB/T 15970.7-2000金屬和合金的腐蝕應(yīng)力腐蝕試驗(yàn)第7部分:慢應(yīng)變速率試驗(yàn)
- 中共一大會(huì)址
- 制度經(jīng)濟(jì)學(xué):05團(tuán)隊(duì)生產(chǎn)理論
- 作文格子紙(1000字)
- 刻度尺讀數(shù)練習(xí)(自制)課件
- 四年級(jí)下冊(cè)美術(shù)課件 4紙卷魔術(shù)|蘇少版
- 七年級(jí)數(shù)學(xué)蘇科版下冊(cè) 101 二元一次方程 課件
- ZL50裝載機(jī)工作裝置設(shè)計(jì)
- 2021年6月浙江省高考讀后續(xù)寫(xiě)課件-高考英語(yǔ)復(fù)習(xí)備考
- 小學(xué)古詩(shī)詞80首(硬筆書(shū)法田字格)
- 時(shí)間單位換算表
評(píng)論
0/150
提交評(píng)論