一、init ramfs是什么
在2.6版本的linux內核中,都包含一個壓縮過的cpio格式的打包文件。當內核啟動時,會 從這個打包文件中導出文件到內核的rootfs文件系統,然后內核檢查rootfs中是否包含有init文件,如果有則執行它,作為PID為1的第一個進 程。這個init進程負責啟動系統后續的工作,包括定位、掛載“真正的”根文件系統設備(如果有的話)。如果內核沒有在rootfs中找到init文件,則內核會按以前版本的方式定位、掛載根分區,然后執行/sbin/init程序完成系統的后續初始化工作。
這個壓縮過的cpio格式的打包文件就是init ramfs。編譯2.6版本的linux內核時,編譯系統總會創建init ramfs,然后把它與編譯好的內核連接在一起。內核源代碼樹中的usr目錄就是專門用于構建內核中的init ramfs的,其中的ini tramfs_data.cpio.gz文件就是init ramfs。缺省情況下,init ramfs是空的,X86架構下的文件大小是134個字節。
二、構建第一個init ramfs:hello world
從C語言開始,學習計算機編程語言的第一個程序幾乎都是hello world,因此我們也構建一個最簡單的hello world式的init ramfs,以說明init ramfs的基本構建方法。
init ramfs的靈魂是init文件(或者叫程序,因為它會被內核第一個執行),我們先寫一個簡單的init程序,它會在內核的console中打印出經典的hello world信息。
hello.c:
#include
#include
int main(int argc,char argv[])
{
printf("hello world, from init ramfs.n");
sleep(9999999);
return 0;
}
其中的sleep()函數語句是為了避免執行時內核很快打出panic的信息,并非功能上的需要。
接著把hello.c編譯成靜態連接程序:
gcc -o hello_static -static -s hello.c
命令行中的-s參數表示編譯后的程序不包含調試定位信息,目的是減少編譯出來的程序文件的大小。
再創建一個init ramfs的構建源文件目錄image,把hello_static程序拷入這個目錄,并改名為init。
在image目錄下,創建一個dev/console的設備文件,否init程序無法在內核console中輸出信息:
mknod -m 600 dev/console c 5 1
注意,執行這個命令需要有root權限。
好了,現在可以設置內核配置參數,進行init ramfs的構建了:
在general setup配置目錄下的init ramfs sources配置項下輸入image的路徑名,比如我的路徑就是/home/wyk/init ramfs-test/image。因為我們的init程序是ELF格式的,所以內核需要支持ELF的可執行文件,否則啟動這個init程序會失敗。在內 核的 Executable file formats配置目錄下,選擇 kernel support for ELF binaries,則可使內核支持ELF格式的可執行文件。其他內核配置參數根據實際需要設置即可,不過,為了減少內核編譯時間,可參考這篇文章 http://linuxman.blog.ccidnet.com/blog-htm-do-showone-uid-60710-type- blog-itemid-293122.html設置一個最簡單的內核配置。
內核配置參數設置完成后,按常規的內核編譯方法進行編譯,init ramfs就自動連接到編譯好的內核映像文件中了。
三、試驗環境搭建
試驗init ramfs需要經常重啟系統,所以使用CPU模擬器是不錯的選擇。我們可以選用qemu,它支持直接啟動linux內核,無需在模擬器中安裝OS。從方便 使用的角度考慮,我們采用qemu launcher設置qemu的各項參數,它的安裝可參考http://linuxman.blog.ccidnet.com/blog-htm-do- showone-uid-60710-type-blog-itemid-612280.html。
在qemu launcher的linux配置標簽中,打勾直接啟動linux,然后在下面的文本框中填上剛才編譯好的內核映像文件的路徑名。因為qemu的運行還需要設置硬盤映像文件,所以還需要在左邊的配置標簽中新建一個硬盤映像文件,但實際上我們并不使用硬盤。
配置好qemu的參數后,點擊launcher按鈕,內核就開始在qemu中運行了。內核輸出一堆內核運行信息后,最后打出了
hello world, from init ramfs.
哈哈,我們構建的init ramfs已經能夠正常工作了!