《Linux內核設計與實現》讀書筆記 第二章 從內核出發

1、獲取內核源碼

1. Git

  • git其實是一種開源的分佈式版本控制工具。
  • Linux做爲一個開源的內核,其源代碼也能夠用git下載和管理html

    - 獲取最新提交到版本樹的一個副本
      - $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
      - 下載代碼後,更新本身的分支到最新分支
      - $ git pull

2.安裝內核源代碼

  • 壓縮形式爲bzip2:$ tar xvjf linux-x.y.z.tar.bz2
  • 壓縮形式爲zip:$ tar xvzf linux-x.y.z.tar.gzlinux

    關於參數:
      -x 解開.tar格式的文件
      -v 顯示詳細信息
      -j 使用bzip2程序
      -z 使用gzip程序
      -f 使用歸檔文件

3. 使用補丁

從內部源碼樹開始,運行$ patch -p1 < ../patch-x,y,zgit

2、內核源碼結構

詳見LINUX內核分析第三週學習總結:構造一個簡單的LINUX系統MENUOS中第一部分:「Linux內核源碼簡介」。安全

目 錄 描 述
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 虛擬化基礎結構
  • COPYIN:內核許可證
  • CREDITS:開發者列表
  • MAINTAINTERS:維護者列表(維護內核子系統和驅動程序)

3、編譯內核

1. 配置內核(關於make與config)

(1)相關

  • Makefile:根據配置的狀況,構造出須要編譯的源文件列表,而後分別編譯,並把目標代碼連接到一塊兒,最終造成 Linux 內核二進制文件。
  • config.in:內核配置文件,給用戶提供配置選擇的功能。
  • 配置工具:包括配置命令解釋器(make config)和配置用戶界面(例如:make menuconfig:基於ncurse庫的圖形界面工具;make gconfig:基於gtk+的圖形工具...)。
  • .config:用戶用來存放內核配置後結果的文件。
  • 能夠配置的各類選項:用CONFIG_FEATURE形式表示,其前綴爲CONFIG。

(2)命令

  • make config:遍歷全部配置項,並讓用戶選擇
  • make deconfig:按默認的配置
  • make oldconfig:先將/boot目錄下的配置文件寫進.config文件中,採用的是註釋的形式寫進新增長的功能。
  • zcat /proc/config.gz > .config:配置選項CONFIG_IKCONFIG_PROC會把完整的壓縮過的內核配置文件存放在/proc/config.gz中,再次編譯時能夠方便地克隆當前的配置。
  • make:默認的Makefile自動化編譯。

2. 其它事項

  • 減小垃圾信息網絡

    $ make > ../detritus
      #將錯誤報告和警告信息重定向到文件中
      $ make > /dev/null
      #將無用的輸出信息重定向到/dev/null中
    
      - /dev/null:空設備,輸入的信息直接丟棄
  • 衍生多個編譯做業:make程序能把編譯過程拆分紅多個並行的做業。其中每一個做業獨立併發地運行,有助於加快多處理器系統上的編譯過程,也有利於改善處理器的利用率。默認狀況下,make只衍生一個做業。併發

    $ make -jn
      #以多個做業編譯內核
    
      - j:指定同時執行多任務
      - n:要衍生出的做業數

3. 安裝新內核

make modules_install
#把全部已編譯的模塊安裝到正確的主目錄/lib/modules下
  • System.map文件:編譯時在內核代碼樹的根目錄下建立的符號對照表。用來將內核符號與它們的起始地址對應起來。

4、內核開發特色

1. 無libc庫/標準頭文件

  • 緣由:(速度與大小)保證內核高效和簡練。
  • 內核源代碼文件不能包含外部頭文件。
    • 基本頭文件:內核源代碼頂級目錄下的include
    • 體系結構相關頭文件:內核源代碼樹的arch/<architecture>/include/asm目錄下
  • printk()函數:把格式化好的字符串拷貝到內核日誌緩衝區上,syslog程序能夠經過讀取該緩衝區來獲取內核信息。

2. 必須使用GNU C

什麼是GNU?GNU是一種操做系統,GNU提供的C編譯器就是咱們以前使用的gcc。

(1)內聯函數

static inline void wolf(unsigned long tail_size);
- static:關鍵字
- inline:用於限定關鍵字
  • 內聯函數:編譯時在它被調用的地方展開。
    • 優勢:減小了函數調用的開銷,性能較好。
    • 缺點:頻繁的使用內聯函數也會使代碼變長,從而在運行時佔用更多的內存。
  • 定義內聯函數特色:時間要求高,自己長度較短的函數。異步

  • 使用以前就要定義好內聯函數,通常在頭文件中定義。分佈式

  • 爲了類型安全和易讀性,優先使用內聯函數而不是複雜的宏。函數

(2)內聯彙編

unsigned int low, high;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
/* low 和 high 分別包含64位時間戳的低32位和高32位 */
- asm:嵌入彙編代碼
- volatile:不優化
  • 彙編語言用於偏近底層或對執行時間嚴格要求的地方。

(3)分支聲明

/* 若是error在絕大多數狀況下爲0(假) */
if (unlikely(error)) {
    /* ... */
}

/* 若是success在絕大多數狀況下不爲0(真) */
if (likely(success)) {
    /* ... */
}
  • 對於條件選擇語句,在一個條件常常/不多出現時,編譯器可經過gcc內建的一條指令對條件分支選擇進行優化。
  • 內核把這條指令封裝成了宏。

3. 沒有內存保護機制

  • 內核本身非法訪問內存的風險
  • 內核中的內存都不分頁:每用掉一個字節,物理內存都減小一個

4. 難以執行浮點運算

  • 使用浮點數時,須要人工保存和恢復浮點寄存器及其餘一些繁瑣的操做。
  • 不建議使用

5. 每一個進程只有一個很小的定長堆棧

  • 內核棧的大小是編譯內核時決定的,對於不用的體系結構,內核棧的大小不同,但都是固定的。(不像用戶空間的棧能夠動態增加)

6. 必須時刻注意同步和併發

  • 緣由:
    • Linux是搶佔多任務操做系統
    • 內核支持對稱多處理器系統(SMP)
    • 中斷異步到來
    • 內核能夠搶佔
  • 經常使用解決方法:自旋鎖和信號量

7. 考慮可移植性的重要性

  • 須要保持的特色:大部分C語言代碼與體系結構無關。

5、總結:關於Linux內核的結構與特色

1. 版本控制

  • 我最先接觸git是剛開始使用實驗樓的時候,實驗樓中的代碼保存須要用到其中「個人代碼庫」功能,實際上就是最簡單的git。
  • Linux內核這種開源的代碼以及不少項目使用git進行版本控制與協做都是挺方便的。
  • 網上有不少教程能夠參考,感受這個比較全面:Git教程,能夠在一些網站上建立本身的代碼庫,好比:git.oschina,操做過就會發現仍是比較簡單的。

2. 依據結構和特色的開發

  • 通讀本章以後感受Linux內核的不少要求與通常的項目實際上是差很少的,它的這些基本結構、開發的特色,對於理解它各個部分的工做過程是頗有幫助的。

參考資料1:《Linux內核設計與實現》(原書第三版)
參考資料2:make config 解惑工具

相關文章
相關標籤/搜索