http://www.ibm.com/developerworks/cn/linux/l-initrd.html
一、從哪裡到哪裡
本文旨在描述linux中核心如何調用啟動,然後如何從img的檔案系統切換到硬碟的過程。
描述起于:linux-2.6.11/init/main.c中函數 static int init(void * unused)
描述止于:/etc/rc.d/rc.sysinit檔案的被調用
二、描寫流程
在linux代碼linux-2.6.11/init/main.c中init這個函數被調用時,初始啟動的檔案
系統鏡像:/boot/initrd-2.6.11.12.img(以2.6.11.12核心為例)已被grub加載到
記憶體中,并已挂載到根目錄上("/")。
1、我們先來看看initrd-2.6.11.12.img到底是個什麼東西:
[[email protected] tmp]# cd /tmp
[[email protected] tmp]# cp /boot/initrd-2.6.11.12.img /tmp/initrd-2.6.11.12.gz
[[email protected] tmp]# gunzip initrd-2.6.11.12.gz
解壓縮後的檔案為:
[[email protected] tmp]# ls -l initrd-2.6.11.12
-rw-r--r-- 1 root root 846848 7月 31 17:01 initrd-2.6.11.12
是一個CPIO格式的檔案,該檔案格式是種檔案鏡像讓我們将它解開到一個目錄中看看
其中的具體内容:
[[email protected] tmp]# mkdir initrd
[[email protected] tmp]# cd initrd
[[email protected] initrd]# cpio -i < ../initrd-2.6.11.12
1654 blocks
[[email protected] initrd]# ls
bin bootsplash dev etc init lib loopfs proc sbin sys sysroot
[[email protected] initrd]# find .
.
./lib
./bin
./bin/nash
./bin/insmod
./bin/modprobe
./bin/hotplug
./etc
./dev
./dev/console
./dev/null
./dev/ram
./dev/systty
./dev/tty1
./dev/tty2
./dev/tty3
./dev/tty4
./loopfs
./proc
./sys
./sysroot
./sbin
./init
./bootsplash
可見該鏡像檔案目錄中包括:
/bin 目錄下的四個用于啟動和切換到硬碟上的程式:
nash(用于處理根目錄下的/init腳本)、insmod和modprobe來加載核心驅動、hotplug用
于外設的拔插處理。
/dev 目錄下的八個裝置檔案
/init 是個nash的啟動腳本檔案
/bootsplash 是核心打了bootsplash更新檔後,會在對該檔案進行讀取操作,然後将該檔案
中包含的圖檔檔案在啟動時顯示。
[[email protected] initrd]# dmesg | grep -i bootsplash
bootsplash 3.1.6-2004/03/31: looking for picture... silentjpeg size 36270 bytes,
...found (1024x768, 19600 bytes, v3).
核心的這個裝載資訊就是在處理該檔案。(具體的bootsplash的使用和建立這裡不細說)。
附:CPIO檔案的打包
[[email protected] initrd]# cd /tmp/initrd
[[email protected] initrd]# rm ../initrd-2.6.11.12
[[email protected] initrd]# find . | cpio -c -o > ../initrd-2.6.11.12
1654 blocks
[[email protected] initrd]# gzip ../initrd-2.6.11.12
[[email protected] initrd]# mv ../initrd-2.6.11.12.gz ../initrd-2.6.11.12.img
2、回到核心init函數中,看看如何調用/boot/initrd-2.6.11.12.img中/init腳本的
....
// 這裡判斷在grub裝載的/boot/initrd-2.6.11.12.img中是否有"/init"這個檔案?
if (sys_access((const char __user *) "/init", 0) == 0)
execute_command = "/init"
else
....
// 如果有"/init"這個檔案就先運作它。
if (execute_command)
run_init_process(execute_command);
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
panic("No init found. Try passing init= option to kernel");
由代碼我們看到kernel會先判斷并運作/boot/initrd-2.6.11.12.img中的/init檔案,我們
來看看該/boot/initrd-2.6.11.12.img/init檔案的内容,我們上面已将該檔案展開到目錄
/tmp/initrd中:
[[email protected] initrd]# cat ./init
#!/bin/nash # 該檔案是個nash的腳本檔案
# 挂接proc檔案系統
mount -t proc /proc /proc
# 不輸出nash調試資訊,由/proc/cmdline決定,cat /proc/cmdline我的啟動參數
# 輸出ro root=/dev/hda3 vga=791 splash=silent,如果該指令行中帶了quiet參
# 數,則不輸出nash提示資訊。
setquiet
# 提示資訊(這裡提示因該放到上面去,mkinitrd-4.2.17-2mgc.rpm包中原來如是,
# 筆誤?為什麼這裡牽涉到mkinitrd這個包類?因為:/boot/initrd-2.6.11.12.img
# 檔案由下面指令生成:mkinitrd /boot/initrd-2.6.11.12.img 2.6.11.12)
echo Mounted /proc filesystem
# 挂接sys檔案系統
echo Mounting sysfs
mount -t sysfs /sys /sys
# 建立/dev臨時目錄
echo Creating /dev
mount -o mode=0755 -t tmpfs /dev /dev
# 建立裝置檔案(這些裝置檔案在切換到硬碟後,由/etc/rc.sysinit中start_udev
# 重新建立)
mknod /dev/console c 5 1
mknod /dev/null c 1 3
mknod /dev/zero c 1 5
# 建立僞終端目錄
mkdir /dev/pts
# 建立共享記憶體目錄
mkdir /dev/shm
# 這裡是調用的nash中的makedevs指令裝載硬碟等塊裝置,不裝載其他裝置隻裝載
# 硬碟等塊裝置
echo Starting udev
# 告訴核心當發現新拔插裝置時用"/sbin/hotplug"程式來處理
echo -n "/sbin/hotplug" > /proc/sys/kernel/hotplug
makedevs
makedevs # 這裡多搞一次沒必要
echo Creating root device
# 由grub啟動指令行root=/dev/hda3來聯接裝置/dev/root到root變量所指定的啟動
# 裝置,見下面我的grub啟動參數:
# kernel /boot/vmlinuz-2.6.11.12 ro root=/dev/hda3 vga=791 splash=silent
mkrootdev /dev/root
# 挂接/dev/root目錄
echo Mounting root filesystem
mount -o defaults --ro -t ext3 /dev/root /sysroot
echo Switching to new root
# 切換根目錄到裝置/dev/root目錄,運作完該指令根目錄"/"->"/dev/hda3"
switchroot --movedev /sysroot
由上面的注釋我們大概能夠明白./init腳本的基本運作流程:
a、裝載基本的核心系統檔案和裝置檔案
b、根據grub的啟動指令行參數,判斷root根檔案裝置,參看/boot/grub/grub.conf檔案中制定
的參數,該參數在核心啟動後可有cat /proc/cmdline顯示出來,nash和其他的一些程式也是通
過讀該系統檔案來去核心啟動參數的。
c、在将從grub啟動參數中獲得根裝置并将其與/dev/root裝置聯接以後,通過nash的switchroot
指令将/dev/root裝置挂接到根目錄上("/")
看看這樣操作後,留下的痕迹:
[[email protected] initrd]# ls -l /dev/root
lrwxrwxrwx 1 root root 9 7月 31 12:06 /dev/root -> /dev/hda3
[[email protected] initrd]# mount
/dev/hda3 on / type ext3 (rw)
到此為止,已将硬碟裝置裝載到根目錄下了,進而取代了原來有initrd.img檔案的根位置。
3、再回頭看看核心中main.c中init函數,看看如何調用/sbin/init處理/etc/inittab檔案
....
// 如果有"/init"這個檔案就先運作它。
if (execute_command)
run_init_process(execute_command);
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
panic("No init found. Try passing init= option to kernel");
我們已經運作完run_init_process(execute_command);這裡了,然後繼續運作:
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
/sbin/init這個檔案在SysVinit-2.85-34mgc.rpm這個包中,該程式的主要處理代碼在檔案:
sysvinit-2.85/src/init.c中,該檔案主要查找和處理/etc/inittab檔案,按照該檔案的内容
依次做處理。
[[email protected] initrd]# cat /etc/inittab
#
# inittab This file describes how the INIT process should set up
# the system in a certain run-level.
#
# Author: Miquel van Smoorenburg, # Modified for RHS Linux by Marc Ewing and Donnie Barnes
#
# Default runlevel. The runlevels used by RHS are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:5:initdefault: # /sbin/init 根據這裡判斷啟動的級别
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit # /sbin/init 會最先運作這個系統配置檔案
l0:0:wait:/etc/rc.d/rc 0 # /sbin/init 根據上面取得的級别運作相應
l1:1:wait:/etc/rc.d/rc 1 # 目錄下的啟動腳本
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now # 設定關機熱鍵
# When our UPS tells us power has failed, assume we have a few minutes
# of power left. Schedule a shutdown for 2 minutes from now.
# This does, of course, assume you have powerd installed and your
# UPS connected and working correctly.
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
# If power was restored before the shutdown kicked in, cancel it.
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1 # 建立6個登陸控制終端可以通過CTRL-ALT-F?
2:2345:respawn:/sbin/mingetty tty2 # 切換,'?'表示第幾個登陸控制台,比如第1
3:2345:respawn:/sbin/mingetty tty3 # 個為F1,第2個為F2依次類推。F7為X11控制
4:2345:respawn:/sbin/mingetty tty4 # 台,後面就沒有了,是以在X下可以很靈活
5:2345:respawn:/sbin/mingetty tty5 # 的切換到控制台下面操作。
6:2345:respawn:/sbin/mingetty tty6
# Run xdm in runlevel 5
x:5:once:/etc/X11/prefdm -nodaemon
通過核心中對/sbin/init的調用現在已經執行/etc/rc.d/rc.sysinit操作了。
閱讀(897) | 評論(0) | 轉發(0) |