[轉載請註明出處] http://kezeodsnx.pixnet.net/blog
作者: kezeodsnx
介紹
先來個展開: initrd==>initial Ram Disk。initial沒什麼好說的,ram disk就比較有趣了。先看看WiKi怎麼說:
A RAM disk is a software layer that enables applications to transparently use RAM, often a segment of main memory, as if it were a hard disk or other secondary storage.
==>是一個軟體層,使得應用程式可"transparently"用RAM,通常就是主記憶體的一塊,然後把這塊ram disk當做storage來用。
首先,transparently很難翻,理解為不透過其他介面/操作,意即直接在ram上存取,而不須搬動資料 (在電腦的世界,程式必須要在ram裡才能執行)。這樣來看,好處就顯而易見了: ram的速度快,performance高 (相對於disk)。缺點呢?沒電資料就不見了。當然也有人做了一些改進缺點的事,不過那是另一個story了 (quote from Jeff.)。
而在kernel document中把initrd介紹為: 提供載入一塊ram disk的能力,誰載入呢?就是boot loader (lilo, grub, etc),因此是由boot loader來做此initialize的動作。這塊ram disk會先被mount成當時的rootfs,也可執行程式 (主要是init)。等到initial好了,就可以把真正的rootfs mount起來。從這段話來看,initrd的功能大概是完成mount rootfs之前的前置工作。有什麼要準備?又為什麼要initrd準備呢?這就值得好好討論一下了 (有請initrd大師--Chris Yang,整個他寫的)。
使用initrd的流程大概是:
1. bootloader負責載入kernel和initrd。
2. kernel解開initrd,並釋放initrd所佔的memory。
3. mount initrd /dev/ram0
4. 執行init
5. mount 真的正rootfs
6. chroot,執行/sbin/init
CPIO
2.6後的kernel,initrd改用cpio的格式,好處是這樣的系統不須要特殊的block device或loop back device。因此只要準備好所須的檔案系統,用以下的cmd,即可製作一個initrd
find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/imagefile.img
解開可用以下cmd:
gunzip -dc /boot/imagefile.img | cpio -idm
Example
從零開始製作initrd的方法不一而足,直接隨便拿一個現成來看吧。
user@user-ubuntu:~/temp/see$ sudo gunzip -dc ../initramfs.img | cpio -idm
2054 blocks
user@user-ubuntu:~/temp/see$ ls
bin dev linuxrc mnt mnt-system mnt-user modules proc sbin sys
可看到基本的filesystem架構,預設會執行linuxrc這支程式。節錄比較具代表的段落
1. 根據/etc/fstab 把相關的fs mount起來,如sys,proc,tmp等
echo "rcS:::mounting filesystems"
mount -a 2>/dev/null
2.如果有需要其他daemon存在,也可叫起來,如udev
echo "rcS:::executing /etc/rc.d scripts"
run-parts -a start /etc/rc.d
echo "mkdir /mnt/rootfs...."
mkdir -p /mnt/rootfs/
3.rootfs在SD卡上,而在掛載真正的rootfs之前,系統並不認識SD這個device,因此要先把driver掛起來,這也是initrd最重要的工作之一。
echo "insmod /home/msm_sdcc.ko...."
insmod /home/msm_sdcc.ko
echo "Sleep 5....."
sleep 5
4. 如果driver已被正確掛載,應該要產生device node。有了device node,就可將真正的rootfs mount起來。之後便可chroot進去,執行第一個程式: /sbin/init
if cat /proc/partitions | grep mmcblk0 > /dev/null;then
echo " Starting mount /dev/mmcblk0...."
mount -t ext3 /dev/mmcblk0 /mnt/rootfs
exec switch_root /mnt/rootfs /sbin/init "$@" </mnt/rootfs/dev/console > /mnt/rootfs/dev/console
fi
5. mount rootfs失敗,進入debug shell
echo "mount rootfs fail......"
/bin/busybox sh
結論
做個小結,initrd中的linuxrc,做了兩件事: 1.掛必須的driver;2. 掛真正的rootfs,並執行/sbin/init。為什麼會在initrd做呢?通常一個distro的發行,會盡量希望能安裝到所有的電腦,但硬體百百種,不可能把所有的driver都build到kernel裡。因此,比較有彈性的方式是維持kernel不動,customize initrd。
留言列表