linux init進程

init 進程是內核初始化完成後啓動的第一個進程。這個進程會創建相應的系統服務,從而使系統正常工作。
init進程會首先讀配置文件/etc/inittab,根據相應的命令,執行相應的腳本,啓動相應的服務。
下面介紹下inittab的規則:
inittab腳本以#開頭的行爲註釋。
inittab腳本的命令格式如下:
label:runlevel:action:process。
詳細解釋如下。
1.label
登記項標誌符,是一個任意指定的、4個字符以內的序列標號,在本文件內必須唯一。
label是1到4個字符的標籤,用來標示輸入的值。但有一些系統只支持2個字符的標籤。
該標籤可以是任意字符構成的字符串。另外LINUX預先定義一些保留的標籤,介紹如下:
id 用來定義缺省的init運行的級別,該標籤定義的語句不執行,只是說明系統默認的運行級別,例如:
   id:5:initdefault:
   就是定義默認運行runlevels=5 ,也就是xwindow
si 是系統初始化的進程
ln 其中的n從1~6,指明該進程可以使用的runlevel的級別
ud 是升級進程
ca 指明當按下Ctrl+Alt+Del是運行的進程
pf 指當UPS表明斷電時運行的進程
pr 是在系統真正關閉之前,UPS發出電源恢復的信號時需要運行的進程
x 是將系統轉入X終端時需要運行的進程


2.runlevels
系統運行級,即執行登記項的init級別。用於指定相應的登記項適用於哪一個運行級,即在哪一個運行級中被處理。
如果該字段爲空,那麼相應的登記項將適用於所有的運行級。
在該字段中,可以同時指定一個或多個運行級,其中各運行級分別以數字0, 1, 2, 3, 4, 5, 6且無須對其進行分隔。
0   Halt,關閉系統.
1   單用戶,在grub啓動時加上爲kernel加上參數single即可進入此運行等級
2   無網絡多用戶模式.
3   有網絡多用戶模式.
4   一般不被系統使用,用戶可以用來設計自己的系統狀態.
5   xwindow模式
6   reboot重啓系統
這裏需要注意的是,系統的默認運行級別一定不能設置爲0或者6.


3.action
表示進入對應的runlevel時,init應該運行process字段的命令的方式,有效的action值如下。
boot:只有在引導過程中,才執行該進程,但不等待該進程的結束。當該進程死亡時,也不重新啓動該進程。
bootwait:只有在引導過程中,才執行該進程,並等待進程的結束。當該進程死亡時,也不重新啓動該進程。
     實際上,只有在系統被引導後,並從單用戶模式進入多用戶模式時,這些登記項才被處理;
     如果系統的默認運行級設置爲2-5(即多用戶模式),那麼這些登記項在系統引導後將馬上被處理。
initdefault:指定系統的默認運行級。系統啓動時,init將首先查找該登記項,如果存在,init將依據此決定系統最初要進入的運行級。
off:如果相應的進程正在運行,那麼就發出一個告警信號,等待20秒後,再通過關閉信號強行終止該進程。如果相應的進程並不存在,那麼就忽略該登記項。
once:啓動相應的進程,但不等待該進程結束便繼續處理/etc/inittab文件中的下一個登記項;當該進程終止時,init也不重新啓動該進程。
   在從一個運行級進入另一個運行級時,如果相應的進程仍然在運行,那麼init就不重新啓動該進程。
powerfail:只在init接收到電源失敗信號時,才執行該進程,但不等待該進程結束。
powerwait:只在init接收到電源失敗信號時,才執行該進程,並在繼續對/etc/inittab文件進行任何處理前等待該進程結束。
respawn:如果相應的進程還不存在,那麼init就啓動該進程,同時不等待該進程的結束就繼續掃描/etc/inittab文件;當該進程終止時,init將重新啓動該進程。
    如果相應的進程已經存在,那麼init將忽略該登記項並繼續掃描/etc/inittab文件。
sysinit:只有在啓動或重新啓動系統並首先進入單用戶模式時,init才執行這些登記項。
     而在系統從運行級1~6進入單用戶模式時,init並不執行這些登記項。"action"字段爲"sysinit"的登記項在"run_level"字段不指定任何運行級。
wait:啓動進程並等待其結束,然後再處理/etc/inittab文件中的下一個登記項。
ctrlaltdel:用戶在控制檯鍵盤上按下Ctrl+Alt+Del組合鍵時,允許init重新啓動系統。


4.process
具體應該執行的命令。


下面以imx6q的linux爲例子說明下init的執行流程。下面先看看imx6q的inittab


# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $


# The default runlevel.
id:5:initdefault:


# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS


# What to do in single-user mode.
~~:S:wait:/sbin/sulogin


# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.


l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
mxc::respawn:/etc/init.d/rc_mxc.S
#mxc0:12345:respawn:/sbin/getty 115200 ttymxc0
# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
#  <id>:<runlevels>:<action>:<process>
#


1:2345:respawn:/sbin/getty 38400 tty1


gpu::sysinit:/etc/init.d/rc_gpu.S


下面是詳細說明:
首先第一句 id:5:initdefault: 說明默認的運行級別是5 也就是默認是xserver的圖形界面
然後執行si::sysinit:/etc/init.d/rcS
也就是運行這個腳本/etc/init.d/rcS,這個腳本實際上就是執行/etc/rcS.d目錄下以S+數字開頭的腳本,按照數字的順序依次執行。
然後執行gpu::sysinit:/etc/init.d/rc_gpu.S,運行/etc/init.d/rc_gpu.S這個腳本。
之後執行~~:S:wait:/sbin/sulogin,運行/sbin/sulogin這個可執行程序。
然後進入運行級別5 
執行l5:5:wait:/etc/init.d/rc 5 ,這個腳本實際上就是執行/etc/rc5.d目錄下以S+數字開頭的腳本,按照數字的順序依次執行。
最後執行mxc::respawn:/etc/init.d/rc_mxc.S,運行/etc/init.d/rc_mxc.S這個腳本


通過上面的說明,我們就可以清楚的知道init啓動腳本的順序了
1 在 /etc/rcS.d目錄下找到以S+數字開頭的腳本,按照數字的順序依次執行。
2 運行/etc/init.d/rc_gpu.S這個腳本。
3 運行/sbin/sulogin
4 在 /etc/rc5.d目錄下找到以S+數字開頭的腳本,按照數字的順序依次執行。
5 運行/etc/init.d/rc_mxc.S這個腳本


最後介紹下在yocto下如何在rc5.d和rcS.d目錄下增加自己的腳本,或者修改已有腳本的順序。
如果要增加一個腳本,我們可以在對應的bb文件中增加下面的語句:
inherit update-rc.d 


INITSCRIPT_NAME = "name"
INITSCRIPT_PARAMS = "start xx level . "
name 是我們的腳本的文件名,這個腳本一定要放在/etc/init.d目錄下
xx 是S後面的數字,level是運行級別,可以是0-5或者S


例如我們要在rcS.d目錄下創建一個S01test.sh的腳本。
那麼我們先將test.sh安裝到/etc/init.d
然後在bb文件增加下面的語句
inherit update-rc.d 


INITSCRIPT_NAME = "test.sh"
INITSCRIPT_PARAMS = "start 01 S . "


重新編譯後燒錄後啓動,我們就可以在/etc/rcS.d會有一個S01test.sh的鏈接文件,指向/etc/init.d/test.sh
如果我們在腳本中加上echo "test.sh run"
我們啓動機器就可以看到test.sh run的串口信息了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章