全面解析Linux 內核 3.10.x - 如何開始
萬事開頭難 - 如何開始?
人總是對未知的事物充滿恐懼!就像航海一樣,在面對危難的時候,船員和船長是一樣心中充滿恐懼的!只是船員始終充滿恐懼,而船長卻能壓抑恐懼並從當前找出突破口!
我沒有船長之能,但也算入行兩年的老船員,我會追隨船長一起尋找突破口!而內核如此龐然大物不知從何入手這真的很正常,那麽應該的入口在哪裏?其實我也不知道,一千個讀者就有一千個哈姆雷特。每個人都入口的理解都不一樣,有人說是必須有著良好的C編程經驗,有人說必須有著對Linux發行版等必要的操作經驗,也有的人說一定要數據結構理解的很好,還有的人說你必須的對各種架構的匯編了如指掌!眼花撩亂的知識你又掌握了多少呢?
我列出三點
1.必須有著良好的C語言理解能力,尤其是指針(靈魂嘛)
2.數據結構確實的能看懂,尤其是鏈表
3.一定要有著非常濃厚的興趣,不成魔,不成活
第3點尤其最重要,因為興趣才是王道
假設你已經對上述內容有了一定的了解或者已經是個老手了!想急需的去更深入的研究內核!
那麽我們就開始吧!
1. 你應該了解內核源碼樹
頂層目錄 ├── arch -- 體系架構相關代碼,內核支持市面上所有的主流架構以及N多種CPU ├── block -- 塊設備子系統 ├── crypto -- 加密解密庫函數 ├── Documentation -- 說明文檔 ├── drivers -- 設備驅動 ├── firmware -- 第三方設備固件 ├── fs -- 文件系統子系統(VFS) ├── include -- 公共頭文件 ├── init -- 啟動初始化子系統(如掛載initrd) ├── ipc -- 進程通信子系統 ├── Kbuild -- 頂層鏈接文件 ├── Kconfig -- 頂層配置配置 ├── kernel -- 內核核心代碼(基本與架構無關,包括調度子系統) ├── lib -- 公共LIB庫函數 ├── Makefile -- 頂層編譯文件 ├── mm -- 內存管理子系統 ├── net -- 不包括網絡設備驅動的網絡子系統 ├── README -- 你懂得 ├── samples -- Demo 代碼 ├── scripts -- 編譯腳本以及工具 ├── security -- 模塊安全相關(SELinux) ├── sound -- 音頻驅動子系統 ├── tools -- 內核輔助工具 ├── usr -- 用戶程序(目前只有一個用於initramfs的cpio打包程序) └── virt -- 虛擬化相關 ├── REPORTING-BUGS -- Bug 上報流程 ├── MAINTAINERS -- 主要維護者(向社區致敬) ├── CREDITS -- 貢獻者(請牢記偉大的程序員)
內核真是太龐大了,目前這個版本的代碼量已經到了幾百萬行之多,那麽問題來了,這麽多的內容我們應該如何取舍?
2. Linux Kernel 核心功能一覽
Linux 核心功能分為五大子系統(進程管理,內存管理,虛擬文件系統,網絡子系統,進程間通信)!
Ps.下面是網上找了一張圖片
- Process Mangement稱作進程管理or進程調度。主要負責管理CPU資源的平衡調度,搶占,異常入口等的管理。主要為了確保各個進程盡量以公平的方式來對CPU執行調度!Ps.這裏其實就要說到優先級等相關內容!這部分是必須要研究的一部分!
- Memory Manager稱作內存管理。主要負責管理內存資源的分配以及配額,確保各個進程任務可以放心去共享使用當前的內存資源。此外,內存管理也會提供虛擬內存機制處理,該機制可以讓進程使用多於系統可用Memory的內存(也就是內存地址轉換),不用的內存會通過文件系統保存在外部非易失存儲器中,需要使用的時候,再取回到內存中。這部分也是必須要研究的一部分!
- IPC稱作進程間通信。它主要負責Linux系統中進程之間的通信,這裏跟硬件無關! 這部分無需多說,必須研究!
- Network稱作網絡子系統,主要負責管理系統的網絡設備,並實現多種多樣的網絡標準以及提供各種各樣協議的基本協議棧。這部分如果從事網絡領域可以仔細研究(難點也是在於協議棧),這部分可以了先了解!
- Virtual File System稱作虛擬文件系統。Linux內核將不同功能的外部設備,例如Disk設備(硬盤、磁盤、NAND Flash、Nor Flash等)、輸入輸出設備、顯示設備等等,抽象為可以通過統一的文件操作接口(open、close、read、write等)來訪問。這部分如果從事存儲就必須要研究啦!它往往是結合塊設備驅動來進行的!
- SELinux/AppArmor號稱最傑出的操作系統安全子系統,最早由NSA(美國國家安全局)來領導並研發的一套安全子系統!這部分內容如果暫時可以先了解下!
Ps…對了,還忘了說一個非常非常重要的核心,那就是體系架構,因為我當前是Mips,所以首先的熟悉MIPS架構中的一些最基本的處理方式,並且內核中有很多關於MIPS的匯編以及GUN混合MIPS的偽匯編,都需要去啃啊,瞬間好頭大!深吸一口氣,慢慢來吧!這部分內容作為整體穿插的時候在進行腦補吧!!!!
3.Makefile
好吧,下一節就要進行實戰了,這裏先腦補一下Makefile.
Makefile作為構建內核的引線,穿插在各個目錄中!那麽對它的語法先簡單的了解下!
基本的 make流程 其實是根據文件的時間戳來更新(讀取Makefile) 文件的編譯工作
從一個樣例來說明Makefile.
main:main.o name.o age.o
gcc main.o name.o age.o -o main
main.o:main.c
gcc -c main.c -o main.o
name.o:name.c
gcc -c name.c -o name.o
age.o:age.c
gcc -c age.c -o age.o
clean:
rm *.o main
基本格式為: 目標生成文件名:源文件
生成過程(得到結果)
clean 作為方便的清除Makefike生成的編譯文件
看上述的主文件
main.c
#include <stdio.h>
extern void name();
extern void age();
int main()
{
name();
age();
return 0;
}
name.c
#include <stdio.h>
void name()
{
printf("My name is Xw. \n");
}
age.c
#include <stdio.h>
void age()
{
printf("My age is 22........\n");
}
- 直接編譯可產生結果。
雜種Shell + Makefile的演變
當我們的可編譯文件越來越多時候,那麽即時可能你少了一個.o文件那也直接導致程序崩潰。
所以這個時候我們的雜種Shell(其實嚴謹的說不是shell相似而已)就有用了。我們大可以用一個變量去代替你的源文件、也可以代替我們的編譯器。如下
CC=gcc //變量代替你的編譯器
OBJS=main.o name.o age.o //源文件
main:$(OBJS)
$(CC) $^ -o $@
main.o:main.c
$(CC) -c $^ -o $@
name.o:name.c
$(CC) -c $^ -o $@
age.o:age.c
$(CC) -c $^ -o $@
clean:
rm *.o main
- 沒有出現的<這些命令以後會用到。分別先介紹一下<這些命令以後會用到。分別先介紹一下@ 表示目標文件的完整名稱 如上述main main.o name.o age.o等
表示所有不重復的依賴包名稱以空格隔開如上述main.omain.c分別可以做依賴包、因為依賴和被依賴僅僅是方向不一樣。其實是可以轉化的。當然上述還可以寫成。表示所有不重復的依賴包名稱以空格隔開如上述main.omain.c分別可以做依賴包、因為依賴和被依賴僅僅是方向不一樣。其實是可以轉化的。當然上述還可以寫成。(CC) -c OBJS?omain.oOBJS?omain.o<表示第一個依賴包名稱
Ps.上述僅僅是Makefile 最基本的使用,在內核裏完全是另外一回事,但是基本語法是一樣的!
*下一節我們就開始內核的Makefile以及其它編譯規則的分析*
全面解析Linux 內核 3.10.x - 如何開始