資源描述:
《linux內核源代碼漫游》由會員上傳分享,免費在線閱讀,更多相關內容在行業(yè)資料-天天文庫。
1、本章試圖以順序的方式來解釋Linux源代碼,以幫助讀者對源代碼的體系結構以及很多相關的unix特性的實現有一個很好的理解。目標是幫助對Linux不甚了解的有經驗的C程序員對整個Linux的設計有所了解。這也就是為什么內核漫游的入點選擇為內核本身的啟始點:系統(tǒng)引導(啟動)。這份材料需要對C語言以及對Unix的概念和PC機的結構有很好的了解,然而本章中并沒有出現任何的C代碼,而是直接參考(指向)實際的代碼的。有關內核設計的最佳篇幅是在本手冊的其它章節(jié)中,而本章仍趨向于是一個非正式的概述。本章中所參閱的任何文件的路徑名都是指主源代碼目錄樹,
2、通常是/usr/src/linux。這里所給出的大多數信息都是取之于Linux發(fā)行版1.0的源代碼。雖然如此,有時也會提供對后期版本的參考。這篇漫游中開頭有圖標的任何小節(jié)都是強調1.0版本后對內核的新的改動。如果沒有這樣的小節(jié)存在,則表示直到版本1.0.9-1.1.76,沒有作過改動。有時候本章中會有象這樣的小節(jié),這是指向正確的代碼以對剛討論過的主題取得更多信息的指示符。當然,這里是指源代碼。引導(啟動)系統(tǒng)當PC的電源打開后,80x86結構的CPU將自動進入實模式,并從地址0xFFFF0開始自動執(zhí)行程序代碼,這個地址通常是ROM-B
3、IOS中的地址。PC機的BIOS將執(zhí)行某些系統(tǒng)的檢測,在物理地址0處開始初始化中斷向量。此后,它將可啟動設備的第一個扇區(qū)讀入內存地址0x7C00處,并跳轉到這個地方。啟動設備通常是軟驅或是硬盤。這里的敘述是非常簡單的,但這已經足夠理解內核初始化的工作過程了。Linux的最最前面部分是用8086匯編語言編寫的(boot/bootsect.S),它將由BIOS讀入到內存0x7C00處,當它被執(zhí)行時就會把自己移到絕對地址0x90000處,并將啟動設備(boot/setup.S)的下2kB字節(jié)的代碼讀入內存0x90200處,而內核的其它部分則
4、被讀入到地址0x10000處。在系統(tǒng)加載期間將顯示信息"Loading..."。然后控制權將傳遞給boot/Setup.S中的代碼,這是另一個實模式匯編語言程序。啟動部分識別主機的某些特性以及vga卡的類型。如果需要,它會要求用戶為控制臺選擇顯示模式。然后將整個系統(tǒng)從地址0x10000移至0x1000處,進入保護模式并跳轉至系統(tǒng)的余下部分(在0x1000處)。下一步是內核的解壓縮。0x1000處的代碼來自于zBoot/head.S,它初始化寄存器并調用decompress_kernel(),它們依次是由zBoot/inflate.c、
5、zBoot/unzip.c和zBoot/misc.c組成。被解壓的數據存放到了地址0x10000處(1兆),這也是為什么Linux不能運行于少于2兆內存的主要原因。[在1兆內存中解壓內核的工作已經完成,見MemorySavers--ED]將內核封裝在一個gzip文件中的工作是由zBoot目錄中的Makefile以及工具完成的。它們是值得一看的有趣的文件。內核發(fā)行版1.1.75將boot和zBoot目錄下移到了arch/i386/boot中了,這個改動意味著對不同的體系結構允許真正的內核建造,不過我將仍然只講解有關i386的信息。解壓過
6、的代碼是從地址0x10100處開始執(zhí)行的[這里我可能忘記了具體的物理地址了,因為我對相應的代碼不是很熟],在那里,所有32比特的設置啟動被完成:IDT、GDT以及LDT被加載,處理器和協(xié)處理器也已確認,分頁工作也設置好了;最終調用start_kernel子程序。上述操作的源代碼是在boot/head.S中的,這可能是整個內核中最有訣竅的代碼了。注意如果在前述任何一步中出了錯,計算機就會死鎖。在操作系統(tǒng)還沒有完全運轉之前是處理不了出錯的。start_kernel()是位于init/main.c中的,并且沒有任何返回結果。從現在起的任何代
7、碼都是用C語言編制的,除了中斷管理和系統(tǒng)調用的入/出代碼(當然,還有大多數的宏都嵌入了匯編代碼)。讓輪子轉動起來在處理了所有錯綜復雜的問題之后,start_kernel()初始化了內核的所有部分,尤其是:設置內存邊界和調用paging_init();初始化中斷、IRQ通道和調度;分析(解析)命令行;如果需要,就分配一個數據緩沖區(qū)(profilingbuffer)以及其它一些小部分;校正延遲循環(huán)(計算“BogoMips”數);檢查中斷16是否能與協(xié)處理器工作。最后,為了生成初始進程,內核準備好了移至move_to_user_mode()
8、,它的代碼也是在同一個源代碼文件中的。然后,所謂的空閑任務,進程號0就進入無限的空閑循環(huán)中運行。接著初始進程(initprocess)嘗試著運行/etc/init、/bin/init或者/sbin/init。如果它們沒有