initrd和initramfs的區別
Linux核心在初始化之後會執行init進程,而init進程會掛載我們的根檔案系統,但由於init程式也是在根檔案系統上的,所以這就有了悖論。Linux採用兩步走的方法來解決這個問題。Linux2.6版以前的方法是:除了核心vmlinuz之外還有一個獨立的initrd.img映像檔案,其實它就是一個檔案系統映像,linux核心在初始化後會mount
initrd.img作為一個臨時的根檔案系統,而init進程就是在initrd.img裡的,然後init進程會掛載真正的根檔案系統,然後umount initrd.img。但Linux2.6核心的實現方式卻不太一樣,雖然完成的功能是一樣的。Linux2.6採用initramfs。initramfs:init ram filesystem,它是一個cpio格式的記憶體檔案系統,製作的方法有兩個,一個是http://blog.csdn.net/htttw/article/details/7215858介紹的,但這樣做出來的initramfs是和核心vmlinuz分開的,因此我們需要在grub裡寫上initramfs的路徑。而另一種方法是把核心和initramfs製作在一起成為一個檔案,方法是在linux源碼make
menuconfig,然後General setup-->選擇Initial RAM filesystem and RAM disk (initramfs/initrd) support,然後在Initramfs source file(s)裡輸入我們的initramfs目錄,然後make bzImage。這種方法做出來的核心就只有一個檔案,不需要指定initramfs了。
下面我們依次介紹:
實驗一:製作傳統的initrd
1.
靜態編譯Busybox,產生_install目錄,具體編譯方法參考:http://blog.csdn.net/htttw/article/details/7215858的前半部分
2.
mkdir ~/ramdisk
cd ramdisk
首先建立一個映像,他就是最終的initrd:
dd if=/dev/zero of=ramdisk bs=1k count=8000
以上命令建立一個8M的ramdisk映像
3.
然後格式化成ext3格式:
mkfs.ext2 -j ramdisk
然後按“y”
4.
然後掛載:
sudo mount ramdisk /mnt -o loop
5.
然後複製busybox下的_install目錄到/mnt下
sudo cp -R busybox/_install /mnt
6.
然後建立必要的目錄,後面就和http://blog.csdn.net/htttw/article/details/7215858的“上面只是準備工作,下面才開始好玩了”後面是一樣的,一直到建立init連結:ln
-sv bin/busybox init之後
注意:現在我們所有的操作都是在/mnt裡進行的,即在第二步產生的ramdisk裡
6.
卸載ramdisk:
sudo umount /mnt
7.
copy到/boot下,準備測試
sudo cp ramdisk /boot/ramdisk
8.
重啟,進入grub命令模式,指定linux和initrd進行測試,具體參考:http://blog.csdn.net/htttw/article/details/7215858的最。如果一切順利,最後我們會進入Busybox。
實驗二:製作現代的initramfs:
上面說過了,製作現代的initramfs有兩種方法,第一種就是http://blog.csdn.net/htttw/article/details/7215858介紹的,下面介紹第二種,即在make
menuconfig裡指定:
1.
準備好_install目錄,然後建立必要的檔案,假設是ramfs目錄
2.
在make menuconfig裡指定Initramfs source file(s)的路徑是第一步的ramfs,然後重新編譯核心:make bzImage
3.
測試,和上面方法是一樣的,不過不用指定initrd了,因為核心和initramfs是編譯在一起的,最後我們會進入Busybox。
這裡插一句,我們完全可以自己寫init進程,只要替換_install目錄裡的init就可以了~~
另外,這裡多加一個小實驗,類比ramfs的掛載與卸載過程:
首先準備好一個busybox的ramdisk,我們把它作為真正的根檔案系統
然後把它copy到我們自己做的ramfs的/root/下,並修改ramfs的etc/init.d/rcS如下:
#!/bin/sh
mount -a
mount /root/ramdisk /mnt
exec switch_root /mnt /sbin/init
這樣最終就mount進我們的根檔案系統裡了。
完成!