閱讀linux內核源碼的過程,是一個將計算機學科的所有理論課程與實際的產品緊密聯系起來的過程。閱讀類UNIX的源碼,在國外操作系統課程的教學過程中,曾經伴隨了一代計算機人才的培養。遺憾的是,我學了幾年計算機專業的課程,直到最近才感覺有了一定的積累,進而閱讀了linux內核的源碼,切實感受到了作為計算機科學與技術精髓的操作系統的魅力所在。
1.Linux和linux內核
很多linux的用戶一直爭論和比較各種linux發行版的易用性,但是大家都認同一點:linux,通常是指linux內核,而且盡管軟件包管理方式不同、圖形界面不同以及上層應用軟件也相應不同,但卻都具有相同的內核--linux內核。內核是一個操作系統最核心的部分,相當於汽車發動機、PC機處理器在各自系統中的核心地位。
由於我內核的閱讀才剛剛起步。所以僅僅針采用x86處理器的PC機器的加電啟動直到linux內核程序被成功加載的過程做一點源碼閱讀級別的闡述。最新的內核是2.6版本的,2.6內核與上一個版本2.4內核的差異還是較大的,這不僅僅表現在源碼的組織上,更在於新內核所采用的諸多新的高性能算法上。
2.4內核的資料在網上眾多,成為我讀懂內核源碼的最為重要的參考。www.linuxidc.com試圖通過尋找內核開發組織的開發者郵件列表以求了解2.4和2.6差異的過程也是艱辛的。時間所限,我並未采取這一方法,而是采取了閱讀2.4資料,對比2.6新版源碼的策略。
在搜索並閱讀相關資料以求搞清楚linux內核到底是如何運轉起來的過程中,我決定借這次課程論文的機會,求同存異,對2.6版本的內核做一點闡述。
linux內核相當復雜。且不說作為操作系統的內核這樣的程序,編寫源碼需要各類技巧,僅僅是所涉及到的知識,分門別類的就有許多許多。可見,內核的閱讀是個長期和反復的過程。也正是如此,一方面,linux牽涉到了計算機領域幾乎所有的知識及其實際運用的過程,內核的閱讀彰顯著迷人的魅力;另一方面,linux內核在操作系統領域的應用如此廣泛,以至於廣大的嵌入式系統開發者都選擇了在某種程度上深入學習linux內核。
2. X86 IBM PC機的啟動過程
由於准備寫這篇文章的時候,最新的穩定版的內核是2.6.35.4,鑒於學習要面向新技術的策略,源碼采用了這個最新的版本。
我對linux內核上層軟件所運行的intel x86處理器相關的內存管理、中斷處理的過程並不太精通,這也限制了我目前對源碼的理解。當然,最為重要的是,是因為機器啟動和內核啟動的過程中,大量的代碼都是純AT&T匯編(.S文件)寫成的,盡管匯編都是直來直去,但面向實際運用的匯編程序也確實是一個難關,何況要想深入理解,還需要大量的intel x86處理器的知識。
一般說來,運行linux 內核的PC計算機的啟動過程是這樣的:
power on -> bios -> bootloader--->kernel boot --->系統初始化(main.c init.c)--->運行應用程序
3. Linux內核啟動協議
閱讀文檔\linux-2.6.35\Documentation\x86\boot.txt
現代支持bzImage的內核的內存布局
程序段地址是由grub的大小來決定的。地址x應該在bootloader所允許的范圍內,盡可能的低。
啟動過程的內存地址分配情況:
| 保護模式的內核 |
100000 +------------------------+
| I/O memory hole |
0A0000 +------------------------+
| 為 BIOS保留 | Leave as much as possible unused
~ ~
| 命令行 | (Can also be below the X+10000 mark)
X+10000 +------------------------+
| 棧/堆 | 棧/堆空間是給內核實模式代碼用的
X+08000 +------------------------+
| Kernel setup | setup代碼運行在內核的實模式下
| Kernel boot 扇區 | The kernel legacy boot sector.
X +------------------------+
| Boot loader |
001000 +------------------------+
| Reserved for MBR/BIOS |
000800 +------------------------+
| Typically used by MBR |
000600 +------------------------+
| BIOS use only |
000000 +------------------------+
傳統上支持image和zimage的內存布局如下(2.4內核就是這樣的布局):
| |
0A0000 +------------------------+
| Reserved for BIOS | Do not use. Reserved for BIOS EBDA.
09A000 +------------------------+
| Command line |
| Stack/heap | For use by the kernel real-mode code.
098000 +------------------------+
| Kernel setup | The kernel real-mode code.
090200 +------------------------+ | Kernel boot sector
| The kernel legacy boot sector.
090000 +------------------------+
| Protected-mode kernel | The bulk of the kernel image.
010000 +------------------------+
| Boot loader | <- Boot sector entry point 0000:7C00
001000 +------------------------+
| Reserved for MBR/BIOS |
000800 +------------------------+
| Typically used by MBR |
000600 +------------------------+
| BIOS use only |
000000 +------------------------+