linu內(nèi)核源碼介紹_第1頁
linu內(nèi)核源碼介紹_第2頁
linu內(nèi)核源碼介紹_第3頁
linu內(nèi)核源碼介紹_第4頁
linu內(nèi)核源碼介紹_第5頁
全文預(yù)覽已結(jié)束

下載本文檔

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

文檔簡介

1、Linux 的內(nèi)核源代碼Linux 的內(nèi)核源代碼可以從很多途徑得到,我一般常常去 看看。 一般來講,在安裝的linux系統(tǒng)下,usr/src/linux目錄下的東西就是內(nèi)核源代 碼。源碼的版本號有一個(gè)非常簡單的編號約定:任何偶數(shù)的核心(例如2.0.30) 都是一個(gè)穩(wěn)定地發(fā)行的核心,而任何奇數(shù)的核心(例如 2.1.42)都是一個(gè)開發(fā) 中的核心。另外還可以從互連網(wǎng)上下載,解壓縮后文件一般也都位于 linux 目錄下。內(nèi)核源代碼有很多版本,目前最新的穩(wěn)定版是 2.2.14。核心源程序的文件按樹形結(jié)構(gòu)進(jìn)行組織,在源程序樹的最上層你會看到這 樣一些目錄:Arch : arch子目錄

2、包括了所有和體系結(jié)構(gòu)相關(guān)的核心代碼。它的每一 個(gè)子目錄都代表一種支持的體系結(jié)構(gòu),例如 i386 就是關(guān)于 intel cpu 及與之相 兼容體系結(jié)構(gòu)的子目錄。PC機(jī)一般都基于此目錄;Include: include子目錄包括編譯核心所需要的大部分頭文件。與平臺 無關(guān)的頭文件在 include/linux 子目錄下,與 intel cpu 相關(guān)的頭文件在 include/asm-i386子目錄下,而include/scsi目錄則是有關(guān)scsi設(shè)備的頭文件 目錄;Init: 這個(gè)目錄包含核心的初始化代碼(注:不是系統(tǒng)的引導(dǎo)代碼),包 含兩個(gè)文件main.c和Version.c,這是研究核心如何工作

3、的一個(gè)非常好的起點(diǎn)。Mm :這個(gè)目錄包括所有獨(dú)立于 cpu 體系結(jié)構(gòu)的內(nèi)存管理代碼,如頁式 存儲管理內(nèi)存的分配和釋放等;而和體系結(jié)構(gòu)相關(guān)的內(nèi)存管理代碼則位于 arch/*/mm/,例女口 arch/i386/mm/Fault.cKernel:主要的核心代碼,此目錄下的文件實(shí)現(xiàn)了大多數(shù)linux系統(tǒng)的 內(nèi)核函數(shù),其中最重要的文件當(dāng)屬sched.c ;同樣,和體系結(jié)構(gòu)相關(guān)的代碼在 arch/*/kernel 中;Drivers: 放置系統(tǒng)所有的設(shè)備驅(qū)動程序;每種驅(qū)動程序又各占用一個(gè)子 目錄:如,/block下為塊設(shè)備驅(qū)動程序,比如ide (ide.c)。如果你希望查看 所 有 可 能 包 含 文

4、件 系 統(tǒng) 的 設(shè) 備 是 如 何 初 始 化 的 , 你 可 以 看 drivers/block/genhd.c中的device_setup()。它不僅初始化硬盤,也初始化網(wǎng) 絡(luò),因?yàn)榘惭b nfs 文件系統(tǒng)的時(shí)候需要網(wǎng)絡(luò)其他: 如, Lib 放置核心的庫代碼; Net, 核心與網(wǎng)絡(luò)相關(guān)的代碼; Ipc, 這個(gè)目錄包含核心的進(jìn)程間通訊的代碼;Fs ,所有的文件系統(tǒng)代碼和各種類型的 文件操作代碼, 它的每一個(gè)子目 錄支持一個(gè)文件系 統(tǒng), 例 如 fat 和 ext2;Scripts, 此目錄包含用于配置核心的腳本文件等。一般,在每個(gè)目錄下, 都有一個(gè) .depend 文件和一個(gè) Makefile

5、 文件,這兩個(gè)文件都是編譯時(shí)使用的 輔助文件,仔細(xì)閱讀這兩個(gè)文件對弄清各個(gè)文件這間的聯(lián)系和依托關(guān)系很有幫 助;而且,在有的目錄下還有 Readme 文件,它是對該目錄下的文件的一些說明, 同樣有利于我們對內(nèi)核源碼的理解。相關(guān)內(nèi)核源代碼分析:1 系統(tǒng)的引 導(dǎo)和初始化: Linux 系統(tǒng)的 引導(dǎo)有好 幾種方式:常見 的 有 Lilo, Loadin 引導(dǎo)和 Linux 的自舉引導(dǎo)(bootsect-loader),而后者所對應(yīng)源程序?yàn)?arch/i386/boot/bootsect.S,它 為實(shí)模式的匯編程序,限于篇幅在此不做分析;無論是哪種引導(dǎo)方式, 最后 都要跳轉(zhuǎn) 到 arch/i386/Ke

6、rnel/setup.S, setup.S 主要是進(jìn)行時(shí)模式下的初始化, 為系統(tǒng)進(jìn)入保護(hù)模式做準(zhǔn)備;此后, 系統(tǒng)執(zhí) 行 arch/i386/kernel/head.S (對經(jīng)壓縮后存放的內(nèi)核要先執(zhí)行 arch/i386/boot/compressed/head.S); head.S 中定義 的一段匯編程序 setup_idt ,它負(fù)責(zé)建立一張256項(xiàng)的idt表(In terrupt Descrip tor Table),此表保存著 所有自陷和中斷的入口地址;其中包括系統(tǒng)調(diào)用總控程序 system_call 的入口地址;當(dāng)然,除此之外, head.S 還 要做一些其他的初始化工作;系 統(tǒng) 初 始

7、 化 后 運(yùn) 行 的 第 一 個(gè) 內(nèi) 核 程 序 asmlinkage void _init start_kernel(void) 定義在/usr/src/linux/init/main.c 中 , 它 通 過 調(diào) 用 usr/src/linux/arch/i386/kernel/traps.c 中的一個(gè)函數(shù)void _init trap_init(void) 把各自陷和中斷服務(wù)程序的入口地址設(shè)置 到 idt 表中, 其中系統(tǒng)調(diào)用總控程序system_cal 就是中斷服務(wù)程序之一 ;void _init trap_init(void) 函數(shù)則通 過調(diào)用一個(gè)宏set_system_gate(SY

8、SCALL_VECTOR,&system_call); 把系統(tǒng)調(diào)用總控程序的入 口掛在中斷0 x80上;其中 SYSCALL_VECTOR 是定義在 /usr/src/linux/arch/i386/kernel/irq.h 中的 一個(gè)常量 0 x80; 而 system_call即為中斷總控程序的入口地址; 中斷總控程序用匯編語言定義在 /usr/src/linux/arch/i386/kernel/entry.S 中;中斷總控程序主要負(fù)責(zé)保存處理機(jī)執(zhí)行系統(tǒng)調(diào)用前的狀態(tài),檢驗(yàn)當(dāng)前調(diào)用是否 合法, 并根據(jù)系統(tǒng)調(diào)用向量,使處理機(jī)跳轉(zhuǎn)到保存在 sys_call_table 表中的相應(yīng)系統(tǒng)服務(wù)例程的

9、入口 ; 從系統(tǒng)服務(wù) 例程返回后恢復(fù)處理機(jī)狀態(tài)退回用戶程序;而系統(tǒng)調(diào)用向量則定義在 /usr/src/linux/include/asm-386/unistd.h 中;sys_call_table 表定義在 /usr/src/linux/arch/i386/kernel/entry.S中 ;同 時(shí)在 /usr/src/linux/include/asm-386/unistd.h中也定義了系統(tǒng)調(diào)用的用戶編程接口;由此可見 , linux 的系統(tǒng)調(diào)用也象 dos 系統(tǒng)的 int 21h 中斷服務(wù), 它把 0 x80 中斷作為總的入口, 然后轉(zhuǎn)到保存在 sys_call_table 表中的各種中斷服

10、務(wù)例程的入口地址 , 形成各種 不同的中斷服務(wù);由以上源代碼分析可知 , 要增加一個(gè)系統(tǒng)調(diào)用就必須在 sys_call_table 表中 增加一項(xiàng) , 并在其中保存好自己的系統(tǒng)服務(wù)例程的入口地址,然后重新編譯內(nèi)核,當(dāng)然,系統(tǒng)服務(wù)例程是必不可 少的。由此可知在此版 linux 內(nèi)核源程序2。2。5中,與系統(tǒng)調(diào)用相關(guān)的源程序文件就 包括以下這些:1arch/i386/boot/bootsect.S 2arch/i386/Kernel/setup.S3arch/i386/boot/compressed/head.S 4arch/i386/kernel/head.S5init/main.c 6arch

11、/i386/kernel/traps.c 7arch/i386/kernel/entry.S8arch/i386/kernel/irq.h 9include/asm-386/unistd.h當(dāng)然,這只是涉及到的幾個(gè)主要文件。而事實(shí)上,增加系統(tǒng)調(diào)用真正要修改文件 只有 include/asm-386/unistd.h和 arch/i386/kernel/entry.S 兩個(gè) ;【三】 對內(nèi)核源碼的修改:在 kernel/sys.c 中增加系統(tǒng)服務(wù)例程如下: asmlinkage int sys_addtotal(int numdata) int i=0,enddata=0; while(i=nu

12、mdata) enddata+=i+;return enddata;該函數(shù)有一個(gè) int 型入口參數(shù) numdata , 并返回從 0 到 numdata 的累加值; 當(dāng)然也可以把系統(tǒng)服務(wù)例程放 在一個(gè)自己定義的文件或其他文件中,只是要在相應(yīng)文件中作必要的說明;把 asmlinkage int sys_addtotal( int) 的入口地址加到 sys_call_table 表中:arch/i386/kernel/entry.S 中的最后幾行源代碼修改前為:.long SYMBOL_NAME(sys_sendfile).long SYMBOL_NAME(sys_ni_syscall) /*

13、streams1 */.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */.long SYMBOL_NAME(sys_vfork) /* 190 */.rept NR_syscalls-190.long SYMBOL_NAME(sys_ni_syscall) .endr修改后為: . .long SYMBOL_NAME(sys_sendfile).long SYMBOL_NAME(sys_ni_syscall) /* streams1 */.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */.long SY

14、MBOL_NAME(sys_vfork) /* 190 */* add by I */.long SYMBOL_NAME(sys_addtotal).rept NR_syscalls-191.long SYMBOL_NAME(sys_ni_syscall).endr把 增 加 的 sys_call_table 表 項(xiàng) 所 對 應(yīng) 的 向 量 , 在 include/asm-386/unistd.h 中進(jìn)行必要申明,以供 用戶進(jìn)程和其他系統(tǒng)進(jìn)程查詢或調(diào)用:增加后的部分 /usr/src/linux/include/asm-386/unistd.h 文件如下: #define _NR_sendfi

15、le 187#define _NR_getpmsg 188#define _NR_putpmsg 189#define _NR_vfork 190/* add by I */#define _NR_addtotal 191測試程序(test.c)如下:#include#include_syscall1(int,addtotal,int, num)main()int i,j;doprintf(Please input a numbern); while(scanf(%d,&i)=EOF);if(j=addtotal(i)=-1)printf(Error occurred in syscall-a

16、ddtotal();n); printf(Total from 0 to %d is %d n,i,j); 對修改后的新的內(nèi)核進(jìn)行編譯,并引導(dǎo)它作為新的操作系統(tǒng),運(yùn)行幾個(gè)程序后可 以發(fā)現(xiàn)一切正常;在新的系統(tǒng)下對測試程序進(jìn)行編譯(*注:由于原內(nèi)核并未提供此系統(tǒng)調(diào)用,所以只有在編譯后 的新內(nèi)核下,此測試程序才能可能被編譯通過),運(yùn)行情況如下:$gcc -o test test.c$./testPlease input a number36Total from 0 to 36 is 666可見,修改成功; 而且,對相關(guān)源碼的進(jìn)一步分析可知,在此版本的內(nèi)核中,從 /usr/src/linux/arch

17、/i386/kernel/entry.S文件中對 sys_call_table 表的設(shè)置可以看出,有好幾個(gè)系統(tǒng)調(diào)用的服務(wù)例程都 是定義在/usr/src/linux/kernel/sys.c 中的同一個(gè)函數(shù): asmlinkage int sys_ni_syscall(void)return -ENOSYS;例如第188 項(xiàng)和第 189 項(xiàng)就是如此:.long SYMBOL_NAME(sys_sendfile).long SYMBOL_NAME(sys_ni_syscall) /* streams1 */.long SYMBOL_NAME(sys_ni_syscall) /* streams2

18、 */.long SYMBOL_NAME(sys_vfork) /* 190 */而這兩項(xiàng)在文件 /usr/src/linux/include/asm-386/unistd.h 中卻申明如下: #define _NR_sendfile 187#define _NR_getpmsg 188 /* some people actually want streams */#define _NR_putpmsg 189 /* some people actually want streams */ #define _NR_vfork 190由 此 可 見 , 在 此 版 本 的 內(nèi) 核 源 代 碼 中 , 由 于 asmlinkage int sys_ni_syscall(void) 函數(shù)并

溫馨提示

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

最新文檔

評論

0/150

提交評論