[轉載請註明出處] 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。

arrow
arrow
    全站熱搜

    kezeodsnx 發表在 痞客邦 留言(1) 人氣()