在嘗試內核開發之前,需要對內核有個整體的瞭解。

###主要內容:

獲取內核源碼
內核源碼的結構
編譯內核的方法
內核開發的特點

1. 獲取內核源碼

內核是開源的,所有獲取源碼特別方便,參照以下的網址,可以通過git或者直接下載壓縮好的源碼包。

http://www.kernel.org

2. 內核源碼的結構

目錄 說明
arch 特定體系結構的代碼
block 塊設備I/O層
crypo 加密API
Documentation 內核源碼文檔
drivers 設備驅動程序
firmware 使用某些驅動程序而需要的設備固件
fs VFS和各種文件系統
include 內核頭文件
init 內核引導和初始化
ipc 進程間通信代碼
kernel 像調度程序這樣的核心子系統
lib 同樣內核函數
mm 內存管理子系統和VM
net 網絡子系統
samples 示例,示範代碼
scripts 編譯內核所用的腳本
security Linux 安全模塊
sound 語音子系統
usr 早期用戶空間代碼(所謂的initramfs)
tools 在Linux開發中有用的工具
virt 虛擬化基礎結構

3. 編譯內核的方法

還未實際嘗試過手動編譯內核,只是用yum更新過內核。這部分等以後手動編譯過再補上。

安裝新的內核後,重啟時會提示進入哪個內核。當多次安裝新的內核後,啟動列表會很長(因為有很多版本的內核),顯得不是很方便。

下面介紹3種刪除那些不用的內核的方法:(是如何安裝的就選擇相應的刪除方法)

3.1 rpm 刪除法

rpm -qa | grep kernel* (查找所有linux內核版本)
rpm -e kernel-(想要刪除的版本)

3.2 yum 刪除法

yum remove kernel-(要刪除的版本)

3.3 手動刪除

刪除/lib/modules/目錄下不需要的內核庫文件
刪除/usr/src/kernel/目錄下不需要的內核源碼
刪除/boot目錄下啟動的核心檔案禾內核映像
更改grub的配置,刪除不需要的內核啟動列表

4. 內核開發的特點

###4.1 無標準C庫

為了保證內核的小和高效,內核開發中不能使用C標準庫,所以連最常用的printf函數也沒有,但是還好有個printk函數來代替。

4.2 使用GNU C,推薦用gcc 4.4或以後的版本來編譯內核

因為使用GNU C,所有內核中常使用GNU C中的一些擴展:

###4.2.1 內聯函數 內聯函數在編譯時會在它被調用的地方展開,減少了函數調用的開銷,性能較好。但是,頻繁的使用內聯函數也會使代碼變長,從而在運行時佔用更多的內存。

所以內聯函數使用時最好要滿足以下幾點:函數較小,會被反覆調用,對程序的時間要求比較嚴格。

內聯函數示例:static inline void sample();

###4.2.2 內聯彙編 內聯彙編用於偏近底層或對執行時間嚴格要求的地方。示例如下:

unsigned int low, high;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
/* low 和 high 分別包含64位時間戳的低32位和高32位 */

###4.2.3 分支聲明 如果能事先判斷一個if語句時經常為真還是經常為假,那麼可以用unlikely和likely來優化這段判斷的代碼。

/* 如果error在絕大多數情況下為0(假) */
if (unlikely(error)) {
    /* ... */
}

/* 如果success在絕大多數情況下不為0(真) */
if (likely(success)) {
    /* ... */
}

4.3 沒有內存保護

因為內核是最低層的程序,所以如果內核訪問的非法內存,那麼整個系統都會掛掉!!所以內核開發的風險比用戶程序開發的風險要大。

而且,內核中的內存是不分頁的,每用一個字節的內存,物理內存就少一個字節。所以內核中使用內存一定要謹慎。

4.4 不使用浮點數

內核不能完美的支持浮點操作,使用浮點數時,需要人工保存和恢復浮點寄存器及其他一些繁瑣的操作。

4.5 內核棧容積小且固定

內核棧的大小有編譯內核時決定的,對於不用的體系結構,內核棧的大小雖然不一樣,但都是固定的。

查看內核棧大小的方法:

ulimit -a | grep "stack size"

##4.6 同步和併發 Linux是多用戶的操作系統,所以必須處理好同步和併發操作,防止因競爭而出現死鎖。

4.7 可移植性

Linux內核可用於不用的體現結構,支持多種硬件。所以開發時要時刻注意可移植性,儘量使用體系結構無關的代碼。


书籍推荐