參考網上許多的教程。
然后有一下相關的筆記:
kernel 在掛載完文件系統后,會執行第一個進程init
這個進程的PID為1
這個進程是所有進程的父進程
init 進程,首先要去讀取inittab中的數據,根據這里面的數據去執行相關的初始化。
在inittab 可以指定默認的運行級別
id:5:initdefault:
還會規定第一個執行的程序
si::sysinit:/etc/init.d/rcS
//指定單用戶模式 ~~:S:wait:/sbin/sulogin
在TI的板子上還規定終端的顯示的開關
0:2345:respawn:/sbin/getty 115200 ttyO0
這里提到,他規定下一個執行的是/etc/init.d/rcS
在/etc/init.d/rcS 內又做了哪些工作呢?
PATH=/sbin:/bin:/usr/sbin:/usr/bin //設置環境變量 runlevel=S //設置運行級別 prevlevel=N umask 022 //設置默認權限補碼 export PATH runlevel prevlevel //對外發布這些變量
trap ":" INT QUIT TSTP //這里話的含義是忽略ctrl + c中斷信號
exec /etc/init.d/rc S //運行/etc/init.d/rc 並加一個參數S
下面進入rc文件分析
1 # rc This file is responsible for starting/stopping 2 # services when the runlevel changes. 3 4 //在文件一開始,就說明了這個文件是當運行級別改變就要更改相關的服務
//設置終端,將 CR 字符映射為 NL 字符,避免階梯效應 stty onlcr 0>&1
# Get first argument. Set new runlevel to this argument. [ "$1" != "" ] && runlevel=$1 if [ "$runlevel" = "" ] then echo "Usage: $0 <runlevel>" >&2 exit 1 fi //如果沒有獲取到運行級別就退出
previous=$PREVLEVEL [ "$previous" = "" ] && previous=N //傳入參數是S的話,則$runleve=S $previous=N export runlevel previous
//若$runlevel=“S”,即檢查rcS.d是否為目錄。 if [ -d /etc/rc$runlevel.d ] then //rcS.d是目錄 PROGRESS_STATE=0 //Split the remaining portion of the progress bar into thirds progress_size=$(((100 - $PROGRESS_STATE) / 3))//progress_size = 100/3 =33 case "$runlevel" in//runlevel=S 0|6) first_step=-100 progress_size=100 step_change=1 ;; S) //Begin where the initramfs left off and use 2/3of the remaining space first_step=$PROGRESS_STATE ///progress_size = 100/3 =33 progress_size=$(($progress_size * 2))//progress_size=66 step_change=1 ;; *) //Begin where rcS left off and use the final 1/3 ofthe space (by leaving progress_size unchanged) first_step=$(($progress_size * 2 + $PROGRESS_STATE)) step_change=1 ;; esac
num_steps=0 for s in /etc/rc$runlevel.d/[SK]*; //s取/etc/rcS.d目錄下以S或K開頭的文件名 do //這句話的含義去掉變量s中所有的/etc/rcS.d/S??的部分 //例:s=/etc/rc$runlevel.d/S10checkroot,那么去掉/etc/rc$runlevel.d/K??部分后,s為checkroot case "${s##/etc/rc$runlevel.d/S??}" in gdm|xdm|kdm|reboot|halt)//若s剩下的文件名中為這五個則跳出for語句 break ;; esac num_steps=$(($num_steps + 1))//num_steps遞加,表示查找到此目錄下/etc/rcS.d有多少個腳本 done//for語句結束
step=0 # First, run the KILL scripts. 首先運行KILL if [ $previous != N ] //由於previous = N ,所以一下不執行 then for i in /etc/rc$runlevel.d/K[0-9][0-9]* do # Check if the script is there. [ ! -f $i ] && continue # Stop the service. startup $i stop done fi
# Now run the START scripts for this runlevel. for i in /etc/rc$runlevel.d/S* do [ ! -f $i ] && continue if [ $previous != N ] && [ $previous != S ] //由於previous為N所以跳過 then # # Find start script in previous runlevel and # stop script in this runlevel. # suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]} stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix # # If there is a start script in the previous level # and _no_ stop script in this level, we don't # have to re-start the service. # [ -f $previous_start ] && [ ! -f $stop ] && continue fi case "$runlevel" in 0|6) startup $i stop ;; *) startup $i start //然后啟動了相關的服務 運行在文件前面定義的 startup 函數 ;; esac done fi
startup函數有如下定義:
# # Start script or program. # startup() { # Handle verbosity [ "$VERBOSE" = very ] && echo "INIT: Running $@..." case "$1" in //判斷第一個參數,如果是一個腳本,執行第一個 *.sh) # Source shell script for speed. ( trap - INT QUIT TSTP scriptname=$1 shift //shift 命令每執行一次,變量的個數($#)減一,而變 量值提前一位 . $scriptname //在執行第一個參數 ) ;; *) //如果不是一個腳本,那么認為是一個服務 "$@" ;; esac startup_progress //再運行前一個函數 }
startup_progress 函數詳解
startup_progress() { step=$(($step + $step_change)) if [ "$num_steps" != "0" ]; then progress=$((($step * $progress_size / $num_steps) + $first_step)) else progress=$progress_size fi #echo "PROGRESS is $progress $runlevel $first_step + ($step of $num_steps) $step_change $progress_size" #if type psplash-write >/dev/null 2>&1; then # TMPDIR=/mnt/.psplash psplash-write "PROGRESS $progress" || true #fi if [ -e /mnt/.psplash/psplash_fifo ]; then echo "PROGRESS $progress" > /mnt/.psplash/psplash_fifo fi echo progress over... }
最后,執行qt.sh
#Uncomment to cause psplash to exit manually, otherwise it exits when it sees a VC switch if [ "x$runlevel" != "xS" ] && [ ! -x /etc/init.d/xserver-nodm ]; then . /etc/init.d/qt.sh # if type psplash-write >/dev/null 2>&1; then # TMPDIR=/mnt/.psplash psplash-write "QUIT" || true # umount /mnt/.psplash # fi fi
參考:
http://www.cnblogs.com/cnland/archive/2013/03/26/2981967.html
https://wiki.archlinux.org/index.php/Arch_boot_process_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)#Init_.E6.B5.81.E7.A8.8B
http://blog.chinaunix.net/uid-17188120-id-4073497.html