RamDisk(Initrd)小結:
名稱:
initrd -- boot loader initialized RAM disk,就是由啓動加載器進行初始化的RAM DISK;
描述:
/dev/initrd這個特殊文件是一個只讀的塊設備文件。/dev/initrd設備文件是一個在內核被啓動之前由啓動加載器進行初始化的RAM disk。
隨後,內核利用/dev/initrd設備文件的內容進行兩個階段的(系統)自舉。
boot loader 會將存儲介質中的內核文件及 initrd文件(initrd會解壓縮後再釋放)加載到內存,然後內核進行初始化,內核啓動時會在訪問真正的根文件系統前先訪問該內存中的 initrd 文件系統。
在(系統)自舉的第一個階段,掛載/dev/initrd中精簡的根文件系統。這個根文件系統包含必備的liunx目錄和程序,甚至也有一個init腳本(或程序linuxrc;在RedHat5中是init),必需的一些驅動模塊;然後執行init腳本,完成加載驅動及模塊的任務;腳本執行後期,會藉助剛纔加載的驅動及模塊掛載上真正的根文件系統,並且切換根文件系統從精簡的initrd根文件系統到根文件系統;
在第二個階段,根文件系統已經被掛載,系統會運行真正根文件系統中的/sbin/init繼續完成系統其它的初始化工作;
(在桌面或服務器 Linux 系統中,initrd 是一個臨時的文件系統。其生存週期很短,只會用作到真實文件系統的一個橋樑。在很多沒有存儲設備的嵌入式系統中,initrd 是永久的根文件系統;)
補充:
在真正的運行環境中,對內核需求是短小而精悍,不應該靜態包含進太多驅動模塊;所以其採用模塊化設計,大部分設備模塊是在需要使用時才加載相應驅動的。但是Linux內核啓動最後一步,需要掛載根文件系統,然後運行/sbin/init創建init內核線程來引導初始化系統。而根文件系統可能在硬盤、磁盤陣列、nfs、flash上,同時根文件系統的格式也是五花八門。此時,要是實在不想包含這麼多驅動到內核的話,可以使用initrd作爲一個過渡。另外,內核在編譯的時候,是可以選擇是否支持initrd,如果使用initrd,則系統自居是兩段式的。如果不使用initrd,需要編譯進去各種驅動(沒做過相關實驗,不發表見解:網上編譯內核教程一堆堆的,但是貌似很多問題,你要感覺那是理所當然的...就引導了o(╯□╰)o);並且如果換新的文件系統,但是恰好內核又沒有更換,這是胡恐怕只有重新編譯內核了而不是僅僅的只mkinitrd就完事大吉了。
下面是2.6內核對模塊選擇路徑:
Linux Kernel Configuration
-> Device Drivers
->Block devices
->RAM block device support
->Default number of RAM disks (設定Ramdisk的個數,默認是16)
->Default RAM disk size (kbytes) (設定Ramdisk的大小,默認4096k)
Linux Kernel Configuration
->General setup
->Inital RAM filesystem and RAM disk(initramfs/initrd) support
如果對Ramdisk的支持已經編譯進內核,我們就可以使用它了,當然對於我RedHat5.4來說默認是使用該項的;
RamDisk文件系統中腳本init作用:
init文件是RamDisk的核心文件,其中的其他文件都是爲該腳本服務的;臨時Mount虛擬root,並自動運行該文件系統中的init腳本 文件 ,這個文件將實際加載真實物理root所需要的設備驅動模塊(如raid或scsi驅動),和文件系統驅動模塊,所有必需的驅動調入後,這個腳本將物理root Mount上,並卸下Ramdisk虛擬根文件系統,此時根文件系統就已經爲真實根文件系統了,然後系統進入正常引導,加載各service ,啓動應用程序;
init腳本的格式:
- #!/bin/nash
- mount -t proc /proc /proc
- setquiet
- echo Mounting proc filesystem
- echo Mounting sysfs filesystem
- mount -t sysfs /sys /sys
- echo Creating /dev
- mount -o mode=0755 -t tmpfs /dev /dev
- mkdir /dev/pts
- mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
- mkdir /dev/shm
- mkdir /dev/mapper
- echo Creating initial device nodes
- mknod /dev/null c 1 3
- mknod /dev/zero c 1 5
- mknod /dev/systty c 4 0
- mknod /dev/tty c 5 0
- mknod /dev/console c 5 1
- mknod /dev/ptmx c 5 2
- mknod /dev/rtc c 10 135
- mknod /dev/tty0 c 4 0
- mknod /dev/tty1 c 4 1
- mknod /dev/tty2 c 4 2
- mknod /dev/tty3 c 4 3
- mknod /dev/tty4 c 4 4
- mknod /dev/tty5 c 4 5
- mknod /dev/tty6 c 4 6
- mknod /dev/tty7 c 4 7
- mknod /dev/tty8 c 4 8
- mknod /dev/tty9 c 4 9
- mknod /dev/tty10 c 4 10
- mknod /dev/tty11 c 4 11
- mknod /dev/tty12 c 4 12
- mknod /dev/ttyS0 c 4 64
- mknod /dev/ttyS1 c 4 65
- mknod /dev/ttyS2 c 4 66
- mknod /dev/ttyS3 c 4 67
- echo Setting up hotplug.
- hotplug
- echo Creating block device nodes.
- mkblkdevs
- echo "Loading uhci-hcd.ko module"
- insmod /lib/uhci-hcd.ko
- echo "Loading ohci-hcd.ko module"
- insmod /lib/ohci-hcd.ko
- echo "Loading ehci-hcd.ko module"
- insmod /lib/ehci-hcd.ko
- mount -t usbfs /proc/bus/usb /proc/bus/usb
- echo "Loading jbd.ko module"
- insmod /lib/jbd.ko
- echo "Loading ext3.ko module"
- insmod /lib/ext3.ko
- echo "Loading scsi_mod.ko module"
- insmod /lib/scsi_mod.ko
- echo "Loading sd_mod.ko module"
- insmod /lib/sd_mod.ko
- echo "Loading scsi_transport_spi.ko module"
- insmod /lib/scsi_transport_spi.ko
- echo "Loading mptbase.ko module"
- insmod /lib/mptbase.ko
- echo "Loading mptscsih.ko module"
- insmod /lib/mptscsih.ko
- echo "Loading mptspi.ko module"
- insmod /lib/mptspi.ko
- echo "Loading dm-mod.ko module"
- insmod /lib/dm-mod.ko
- echo "Loading dm-mirror.ko module"
- insmod /lib/dm-mirror.ko
- echo "Loading dm-zero.ko module"
- insmod /lib/dm-zero.ko
- echo "Loading dm-snapshot.ko module"
- insmod /lib/dm-snapshot.ko
- echo Waiting for driver initialization.
- stabilized --hash --interval 250 /proc/scsi/scsi
- echo Making device-mapper control node
- mkdmnod
- mkblkdevs
- echo Scanning logical volumes
- lvm vgscan --ignorelockingfailure
- echo Activating logical volumes
- lvm vgchange -ay --ignorelockingfailure VolGroup00
- resume /dev/VolGroup00/LogVol01
- echo Creating root device.
- mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00
- echo Mounting root filesystem.
- mount /sysroot
- echo Setting up other filesystems.
- setuproot
- echo Switching to new root and running init.
- switchroot
腳本執行過程分析:
第一行#!/bin/nash是一個redhat自己的微型解釋器。只包含精簡的命令,能做基本的mount、insmod、mkdev等,主要是爲了減小iitrd體積;
mount命令掛載上了initrd釋放出來的各種內核文件系統/proc、/sys、/dev到相應的位置;
mknod生成各種設備節點;hotplug開始監聽系統總線熱插拔的磁盤等uevent事件。mkblkdevs將這些熱插拔的磁盤節點創建到/dev下。
接着insmod開始安裝usb,block設備,scsi設備,ide設備,device-mapper的設備驅動,隨後系統總線就會收到這些事件,mkblkdevs又會把他們的節點創建到/dev下。我們的硬盤多數是在這個階段被找到並創建了相應的設備節點。然後是加載啓動邏輯卷管理,使我們的設備能使用邏輯卷名稱。這一步可以不要的
然後是加載啓動邏輯卷管理,使我們的設備能使用邏輯卷名稱;(該步驟非必要)
(重要)下面mkrootdev:該命令可以創建根文件系統的設備節點;查找內核參數當中的“root=”項;然後解析mkrootdev後面的-t 和-o參數,如果-t是nfs,而且,-o中包含dhcp,那麼root的相關信息從dhcp主機取得,如果-o選項不包含dhcp或者-t不是nfs, 則從root=內核參數取真正root文件系統的位置,如果沒有root=參數,使用mkrootdev後面的設備作爲root設備。如果是-t nfs那麼直接添加入口到/etc/fstab文件,包括-t的文件系統類型和-o的選項。如果-t指定的文件系統不是nfs,那麼它創建名稱爲/dev/root的節點,它的Major,Minor設備號使用root=參數的設備號(如果有),或mkrootdev後面的設備的設備號。;它不僅能夠根據root=/dev/xxx來生成對應的設備節點,還能夠在碰到root=LABEL=/ 的情況下探測所有的硬盤分區,以便找到對應着卷標爲/的分區。
所以,mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00這行,會將一條入口信息寫入內存中的/etc/fstab,如: /dev/root /sysroot ext3 defaults,ro 0 0 ;注意此時設備是/dev/root.而不是/dev/VolGroup00/LogVol00,但他們的設備號是一樣的。
緊接着後面的mount /sysroot;就會讀取/etc/fstab並加載剛剛mkrootdev寫入的這條入口信息所指定的設備,這就是加載/dev/root 到/sysroot下。這時我們的真正的root才被加載到了系統中。nash在mount時,如果只有一個參數,以它作爲root加載點,且它必須是 /sysroot(會同fstab中的做比較)。如果有加載點和設備參數,-t -o必須也被提供,mount丟棄/etc/fstab中的入口的內容,而使用參數提供的信息加載root設備。若如本例,至此/sysroot下是真正物理系統的root分區。/是initrd的內存盤。
setuproot 並不接受任何參數,而以上面的/sysroot作爲我們的root。安裝所有的子分區到/sysroot下。也就是建立我們的根文件系統樹,如果我們的root 不是由單個分區組成的話。這些信息從/sysroot/etc/fstab.sys中讀取。如果它不存在,就從initrd的/etc /fstab.sys中讀取。如果仍然不存在,就建立默認的文件系統樹:
掛載(Bind掛載方式)/proc 到/sysroot/proc ,/sys到/sysroot/sys
最後switchroot卸載/dev,/proc,/sys文件系統,掛載(移動掛載方式)/sysroot到/下面.,然後卸載initrd的/。打開 /dev/console到描述符3,將stdin,stdout,stderr全部定向到3(console),分析內核參數,尋找init=,如果有,以它作爲init程序執行,否則,執行默認:搜尋第一個找到的/sbin/init;/etc/init;/bin/init;/bin/sh執行,這就 是所有進程的父進程0
文章參考:
關於Linux-gate.so.1的含義: http://www.linuxidc.com/Linux/2007-07/6221.htm
Linux boot process (initrd part):http://bbs.kylin-linux.com/htm_data/9/1003/209.html
http://www.mike.org.cn/articles/linux-xiangjie-linux-initrd/
拓展參考: http://www.ibm.com/developerworks/cn/linux/l-initrd.html(IBM上面用busybox實現了一個精簡的initrd)
整理過程,難免出錯,希望共同探討;