1. 程式人生 > >Linux系統記憶體磁碟初始化技術詳細解析

Linux系統記憶體磁碟初始化技術詳細解析

轉http://unix-cd.com/unixcd12/article_6520.html

initrd掛載優先順序高於真實根檔案系統,它被邦定在核心上,做為核心啟動過程的一部分被載入(load)。然後,做為兩階段引導過程的第一部分,核心掛載(mount)initrd,用於獲得並載入真實有效的檔案系統。

為了達到這個目的,initrd包含有最起碼的目錄與程式,例如insmod,來安裝核心模組到核心中。

對於桌面或伺服器linux,initrd是臨時檔案系統,它的生存週期很短,僅僅是做為到達真實根檔案系統的橋樑。但對於沒有儲存裝置的嵌入式系統來說,它才是永久性的根檔案系統。本篇文章對這兩方面均有涉及。

<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script>

2 深入分析initrdL

initrd包含有必須的程式和系統檔案,用於支援系統的啟動的第二階段過程。建立 初始化記憶體的方法,是隨著你所使用的系統版本而改變的。從Fedora Core3以後,initrd就由回送裝置(loop device)建立。什麼是回送裝置?它是一個裝置驅動,允許你將一個檔案掛載為塊裝置,並對其檔案系統做出描述。也許loop device並不存在與你的核心中,但是你能夠通過核心的配置工具(make menuconfig)開啟它。路徑是:Device Drivers-》Block Devices-》LoopBack Device support。下面為檢查命令:

# mkdir temp ; cd temp 

# cp /boot/initrd.img.gz .

# gunzip initrd.img.gz

# mount -t ext -o loop initrd.img /mnt/initrd

# ls -la /mnt/initrd

#

現在,你可以通過檢視/mnt/initrd的子目錄來檢視initrd的內容。需要注意的是,即使你的initrd映象檔案並不是以.gz做為字尾名,但是你同樣可以通過增加此後綴名來讓gunzip開啟它。

從Fedora Core3開始,預設的initrd映象就是一個壓縮的gpio歸檔檔案。除了用掛載檔案的方式以外,你同樣可以通過cpio歸檔的方式來將其掛載成使用了回送裝置的壓縮映象。你可以通過以下的指令來檢查這個cpio歸檔檔案的內容:

# mkdir temp ; cd temp 

# cp /boot/initrd-2.6.14.2.img initrd-2.6.14.2.img.gz

# gunzip initrd-2.6.14.2.img.gz

# cpio -i --make-DirectorIEs < initrd-2.6.14.2.img

你看到的結果將是一個小型根檔案系統,如下所示:

# ls -la 

#

drwxr-xr-x 10 root root 4096 May 7 02:48 .

drwxr-x--- 15 root root 4096 May 7 00:54 ..

drwxr-xr-x 2 root root 4096 May 7 02:48 bin

drwxr-xr-x 2 root root 4096 May 7 02:48 dev

drwxr-xr-x 4 root root 4096 May 7 02:48 etc

-rwxr-xr-x 1 root root 812 May 7 02:48 init

-rw-r--r-- 1 root root 1723392 May 7 02:45 initrd-2.6.14.2.img

drwxr-xr-x 2 root root 4096 May 7 02:48 lib

drwxr-xr-x 2 root root 4096 May 7 02:48 loopfs

drwxr-xr-x 2 root root 4096 May 7 02:48 proc

lrwxrwxrwx 1 root root 3 May 7 02:48 sbin -> bin

drwxr-xr-x 2 root root 4096 May 7 02:48 sys

drwxr-xr-x 2 root root 4096 May 7 02:48 sysroot

#

一些小的,但是很有必要的程式組合能在./bin目錄下得到,包括nash(它不是一個shell,而是一個指令碼解釋工具),用於載入核心模組的insmod,以及lvm等。

上面所示目錄中,相對比較有趣的是root目錄下的初始化檔案。這些檔案,和傳統的linux啟動過程中一樣,是在initrd映象被解壓縮到RAM中時生成的。待會我們將繼續探討這個問題。

3 建立initrd的工具。

現在,讓我們回到一開始的討論:initrd的映象是如何被建立的?在傳統的 linux系統中,initrd是在linux build的時候被建立的。像mkinitrd這樣的許許多多的工具,都能夠用於通過必須的庫和模組來自動構建一個用於過渡到真實根檔案系統的 initrd。事實上,mkinitrd工具是一個指令碼檔案,因此,我們能夠很清楚得看到,這個過程是如何進行的。同樣的,YAIRD (Yet Another Mkinitrd)工具,也允許我們自定製每一個initrd被構建的階段。

4 自己動手,打造自定義的初始化記憶體盤

由於很多基於linux的嵌入式系統都沒有硬碟驅動器,initrd也可以做為永久 性的根檔案系統。下面我就將告訴你們,如何建立一個initrd映象。我使用的是標準linux桌面系統,因此大家即使沒有嵌入式目標裝置也可以照著做。 除了交叉編譯以外,嵌入式目標檔案的構建過程是相同的。

#!/bin/bash 

# Housekeeping...

rm -f /tmp/ramdisk.img

rm -f /tmp/ramdisk.img.gz

# Ramdisk Constants

RDSIZE=4000

BLKSIZE=1024

# Create an empty ramdisk image

dd if=/dev/zero of=/tmp/ramdisk.img bs=$BLKSIZE count=$RDSIZE

# Make it an ext2 mountable file system

/sbin/mke2fs -F -m 0 -b $BLKSIZE /tmp/ramdisk.img $RDSIZE

# Mount it so that we can populate

mount /tmp/ramdisk.img /mnt/initrd -t ext2 -o loop=/dev/loop0

# Populate the filesystem (subDirectorIEs)

mkdir /mnt/initrd/bin

mkdir /mnt/initrd/sys

mkdir /mnt/initrd/dev

mkdir /mnt/initrd/proc

# Grab busybox and create the symbolic links

pushd /mnt/initrd/bin

cp /usr/local/src/busybox-1.1.1/busybox .

ln -s busybox ash

ln -s busybox mount

ln -s busybox echo

ln -s busybox ls

ln -s busybox cat

ln -s busybox ps

ln -s busybox dmesg

ln -s busybox sysctl

popd

# Grab the necessary dev files

cp -a /dev/console /mnt/initrd/dev

cp -a /dev/ramdisk /mnt/initrd/dev

cp -a /dev/ram0 /mnt/initrd/dev

cp -a /dev/null /mnt/initrd/dev

cp -a /dev/tty1 /mnt/initrd/dev

cp -a /dev/tty2 /mnt/initrd/dev

# Equate sbin with bin

pushd /mnt/initrd

ln -s bin sbin

popd

# Create the init file

cat >> /mnt/initrd/linuxrc << EOF

#!/bin/ash

echo

echo "Simple initrd is active"

echo

mount -t proc /proc /proc

mount -t sysfs none /sys

/bin/ash --login

EOF

chmod +x /mnt/initrd/linuxrc

# Finish up...

umount /mnt/initrd

gzip -9 /tmp/ramdisk.img

cp /tmp/ramdisk.img.gz /boot/ramdisk.img.gz

想建立initrd的話,你需要首先建立一個空檔案,將/dev/zero(0字元 流)做為ramdisk.img的輸入。得到的檔案大小大約是4MB(有4000個1K的塊組成)。接下來,用mke2fs命令來建立一個使用這個空檔案 的ext2檔案系統。現在,這個檔案就是一個ext2檔案系統。ok,接下來,以迴路裝置的形式掛載這個檔案到/mnt/initrd,現在,你就在掛載 點擁有一個代表著ext2檔案系統的目錄,並用與存放你的initrd。其他大多數的指令碼語句都是用於實現這個功能。

下一步,就是建立一些必須的子目錄,用於生成你的根檔案系統: /bin, /sys, /dev, 和 /pro。這裡只需要少數幾個目錄,例如,沒有/lib。但是它們已經包含了大部分功能。

如果想讓你的根檔案系統發揮更大的作用,請使用 BusyBox。這個工具是一個包含了許多獨立工具的映象,這些獨立的工具你都能在linux中找到( ash, a等等wk, sed, insmod)。BusyBox的優勢在於,它把它們集合在了一起,並分享了公用的部分,從而極大縮小了映象的體積。這對於嵌入式系統來講,是非常理想 的。請將BustBox映象從它的源目錄中複製出來,到你的/bin目錄下,這樣,很多指向BusyBox工具集的符號連結將被建立,BusyBox能確 定哪一個工具將被使用,並自動引用它。這個/bin目錄下被建立的連結的小型集合將用於對啟動指令碼的支援。

再下一步,就是一小部分特殊裝置檔案的建立。我從我的/dev資料夾中直接拷貝了出來,別忘了加上-a選項來保持它們原有的屬性。

倒數第二步,就是生成linuxrc檔案。在核心掛載了記憶體盤之後,它將搜尋並執行 相關的啟動檔案,如果沒有找到,核心就將linuxrc檔案做為其啟動指令碼。你最好在這個檔案中對環境變數做一些基本設定,例如掛載/proc檔案系統 等。除了/proc外,我還掛載了/sys檔案系統,將訊息傳送給終端。最後,我呼叫ash並通過它和根檔案系統互動。最後記住,用chmod把 linuxrc檔案的屬性改為可執行。

最後,你的根檔案系統算是ok了。現在它並沒有被掛載,用gzip將它壓縮,並將壓縮後的檔案ramdisk.img.gz拷貝到/boot目錄下,這樣它就能被GRUB呼叫。

想要構建你的初始化ram盤的話,你只需要呼叫mkird,映象就將自動建立並拷貝到/boot目錄下。