下面的實驗以 debian7.5 64bit 為例.
獲取源碼
獲取 debian7.5 本身的源碼非常簡單:
sudo apt-get install linux-source
https://www.kernel.org/ 的git上提供的源碼分支非常多, 剛開始學習源碼主要關注下面幾個分支:
- linus分支: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/
linux創始人的分支, 不用說肯定最重要, 它是所有分支的根源. 處於 "mainline" 的地位.
這個分支還有個好聽的名字 – "vanilla(香草)" 內核. - linux-next樹: https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/
這個一個為發布將來的版本而積累新代碼並進行測試的源碼樹.
由 Stephen Rothwell 等人進行管理和維護 - stable樹: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/
這是一個主要針對過去發布的內核版本進行bug修改, 使其更加穩定的樹.
由 Greg Kroah-Hartman, Chris Wright 進行管理和維護.
針對某個Linus樹的穩定版維護一般持續6個月左右, 也有更持久的.
上面的列出的git樹中都可以獲取想要的源碼.
編譯內核
其實編譯內核和編譯普通軟件也沒多大區別, 只是內核編譯的參數非常之多.
下面就來先看看如何設置內核編譯參數
內核編譯選項
-
編譯選項個數
內核的編譯選項的個數非常多, v2.6.38的內核中就有 12 000 個左右的設置選項(這是包含所有arch的配置選項).
內核編譯選項不僅多, 有些編譯選項之間還存在依賴關系, 所以手動設置編譯選項幾乎是不可能的.
值得慶幸的是, 只要知道自己需要設置的那些選項, 就可以使用 make ***config 來進行設置, 它還會自動處理依賴關系. -
配置編譯選項:
設置內核編譯選項是通過 kconfig 這個工具來完成的.
kconfig 的源碼就是內核代碼中 script/kconfig 目錄下各個編譯選項的選擇有3種方式:
- =y :: 直接編譯到內核中
- =m :: 以模塊方式編譯到內核中
- 不設置 :: 不編譯
編譯方法:
- make menuconfig :: 源碼根目錄下生成 .config (沒有會自動生成), .config中就是各個內核編譯選項的選擇狀況.
- make defconfig :: 根據當前系統的架構默認 .config 生成內核源碼目錄下的 .config (每個架構的配置文件: ex. arch/x86/configs/x86_64_defconfig)
- make oldconfig :: 將已有的 .config 放到源碼根目錄下后執行, 目的是為了復用之前的內核編譯選項的配置.
- make xconfig :: 圖形化配置, 需要qt3, 個人覺得沒有必要, 有 make menuconfig 就足夠了.
- make localmodconfig :: 生成以正在使用的內核模塊為對象的 .config
編譯
編譯很簡單, 內核編譯選項設置好之后, 只需簡單的命令 make, 就可以編譯了.
由於內核代碼的龐大, 所以和一般應用程序相比, 編譯時間會很長. 可以嘗試以下方法來加快編譯速度:
-
不用的驅動程序都不要設置, 這樣就不會編譯
-
利用make的 -j 選項來並發編譯, ex. make -j N (N是並發數). 如果你的機器有2個CPU, 可以用 make -j 2 來提高編譯速度
-
使用 make localmodconfig 來生成僅以正在使用的內核模塊為對象的 .config (一般這樣生成的.config中包含的內核模塊最少, 所以編譯速度快)
-
編譯時間比較: 測試環境 - debian v7.5虛擬機(cpu: 單核, 內存: 512MB)
.config生成 | make時間 | 生成的modules | 備注 |
---|---|---|---|
make menuconfig | 1小時13分41秒 | 3052個.ko, 共1.2GB | 默認配置, 什么也不選擇 |
make localmodconfig | 19分36秒 | 337 個.ko, 共176MB |
注 modules 是通過 make modules_install 之后, 在 /lib/modules 中根據編譯內核版本號來查看的
查看有多少個 .ko 文件的方法:
cd /lib/modules/3.2.60
find . -name '*.ko' | wc -l
分開編譯
模塊和內核不在一起的編譯, 就是在現有的內核中追加一些內核模塊時, 不需要將內核也重新編譯.
模塊分開編譯的方法很簡單, 參考之前的博客: 《Linux內核設計與實現》讀書筆記(六)- 內核數據結構 這篇博客中的例子就是和內核分開編譯的模塊.
交叉編譯
交叉編譯就是在當前平台上編譯其他平台上的內核二進制映像, 比如在 x86_64 平台上編譯 arm 的內核映像.
交叉編譯需要目標平台的交叉編譯器. 編譯時主要是 ARCH 和 CROSS_COMPILE 2個變量的設置.
下面舉個交叉編譯 ARM 的例子: 公司用的制作 Cubieboard 板子上的image中的一段編譯內核的代碼
make -C ${CB_KSRC_DIR} O=${CB_KBUILD_DIR} ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- kernel_defconfig
make -C ${CB_KSRC_DIR} O=${CB_KBUILD_DIR} ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j4 INSTALL_MOD_PATH=${CB_TARGET_DIR} uImage modules
上述 第一行 是編譯內核源碼. 第二行 是創建 uImage 格式的內核映像以及創建內核模塊
最終在 INSTALL_MOD_PATH 生成的內核模塊可以直接拷貝到 arm機器上使用.
生成內核包
debian 系 linux下生成 內核源碼包的方法
make deb-pkg
安裝內核
make modules_install (安裝內核模塊到 /lib/modules 下)
make install (安裝內核二進制映像, 生成並安裝boot初始化文件系統映像文件)
卸載內核
- 刪除/lib/modules/目錄下不需要的內核庫文件
- 刪除/usr/src/kernel/目錄下不需要的內核源碼
- 刪除/boot目錄下啟動的核心檔案禾內核映像
- 更改grub的配置,刪除不需要的內核啟動列表
內核 Makefile 中一些有用的 target
- make help : 內核Makefile中的各種 target
- make cscope : 生成 cscope 文件
- make tags/TAGS : tags可用於vim, TAGS可用於emacs