關於linux的啟動流程的筆記(轉)

BSDLite發表於2007-08-15
關於linux的啟動流程的筆記(轉)[@more@]
CODE:
[b]一、從哪裡到哪裡[/b]
本文旨在描述linux中核心如何呼叫啟動,然後如何從img的檔案系統切換到硬碟的過程。
描述起於:linux-2.6.11/init/main.c中函式 static int init(void * unused)
描述止於:/etc/rc.d/rc.sysinit檔案的被呼叫

[b]二、描寫流程[/b]
在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到底是個什麼東西:
[root@wj-server1 tmp]# cd /tmp
[root@wj-server1 tmp]# cp /boot/initrd-2.6.11.12.img /tmp/initrd-2.6.11.12.gz
[root@wj-server1 tmp]# gunzip initrd-2.6.11.12.gz
解壓縮後的檔案為:
[root@wj-server1 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格式的檔案,該檔案格式是種檔案映象讓我們將它解開到一個目錄中看看
其中的具體內容:
[root@wj-server1 tmp]# mkdir initrd
[root@wj-server1 tmp]# cd initrd
[root@wj-server1 initrd]# cpio -i < ../initrd-2.6.11.12
1654 blocks
[root@wj-server1 initrd]# ls
bin bootsplash dev etc init lib loopfs proc sbin sys sysroot
[root@wj-server1 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補丁後,會在對該檔案進行讀取操作,然後將該檔案
中包含的圖片檔案在啟動時顯示。
[root@wj-server1 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檔案的打包
[root@wj-server1 initrd]# cd /tmp/initrd
[root@wj-server1 initrd]# rm ../initrd-2.6.11.12
[root@wj-server1 initrd]# find . | cpio -c -o > ../initrd-2.6.11.12
1654 blocks
[root@wj-server1 initrd]# gzip ../initrd-2.6.11.12
[root@wj-server1 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中:
[root@wj-server1 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裝置掛接到根目錄上("/")

看看這樣操作後,留下的痕跡:
[root@wj-server1 initrd]# ls -l /dev/root
lrwxrwxrwx 1 root root 9 7月 31 12:06 /dev/root -> /dev/hda3
[root@wj-server1 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檔案,按照該檔案的內容
依次做處理。

[root@wj-server1 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操作了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617542/viewspace-959977/,如需轉載,請註明出處,否則將追究法律責任。

關於linux的啟動流程的筆記(轉)
請登入後發表評論 登入
全部評論

相關文章