在linux的發展過程中,
linux
的啟動程式也在發展,從
sysv init
到現在的
upstart
、systemd,
通常該程式是程序號為
1的程序,該程式在
linux
系統有著舉足輕重的地方。在
openwrt
中,使
用了另外一種啟動程式叫做
procd
,本文的重點並不在於介紹
procd
,本文主要介紹並解析
procd
、preinit
及各種指令碼如何完成整個系統的初始化。
linux發行版:
ubuntu14.04 lts
openwrt版本:
barrier break 14.07 r42635
(linux kernel 3.10.49)
硬體:mpr-a2
模組(rt5350)
在檢視linux
核心**及根檔案系統下的指令碼之前,需要對
openwrt
進行配置,執行
make menuconfig,在
target system
中選擇ralink rt288x/rt3***
,subtarget
中選擇rt3x5x/rt5350
based boards
,target profile
選擇hame mpr-a2
,然後make
完成openwrt
的編譯。打完
patch
的核心
**在build_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/linux-ramips_rt305x/
目錄下,根檔案系統目 錄在
build_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/root-ramips/。
linux的啟動入口為
start_kernel()
(init/main.c
),該函式的最後會呼叫
rest_init()
(init/main.c),
該函式建立兩個核心執行緒
init
和kthreadd
之後,進入死迴圈,即所謂的
0號程序。init執行緒執行
kenrel_init()
(init/main.c
)函式,在
kernel_init
函式中,首先會檢查核心的啟動引數中是否有設定
init
引數,如果有,則會使用該引數指定的程式作為
init
程式,否則會按照如下**(打上
patch
後的)
中所示的順序依次嘗試啟動,如果都無法啟動就會導致
kernel panic。
if (!run_init_process("/etc/preinit") ||
!run_init_process("/sbin/init") ||
!run_init_process("/etc/init") ||
!run_init_process("/bin/init") ||
!run_init_process("/bin/sh"))
return 0;
在目前的環境下,核心啟動引數未設定init
引數,所以會以
/etc/preinit
程式作為
init
程式,preinit
實際為shell
指令碼。 /etc/preinit
/lib/functions.sh
/lib/functions/preinit.sh
/lib/functions/system.sh
/lib/preinit/下所有指令碼
在proc
程式包中,編譯完會生成兩個可執行程式:
init
和procd
,均在目 錄
/sbin
下,這兩個程式均會使用到。
這個初始化過程遵循如下主線:
下面我們一步一步分析這個過程。
在/etc/preinit指令碼中,第一條命令如下:
[ -z "$preinit" ] && exec /sbin/init
在從核心執行這個指令碼時,preinit
這個變數時沒有定義的,所以會直接執行
/sbin/init
。/sbin/init
程式主要做
了一些初始化工作,如環境變數設定、檔案系統掛載、核心模組載入等,之後會建立兩個程序,分別執行
/etc/preinit 和
/sbin/procd
,執行/etc/preinit
之前會設定變數
preinit
,/sbin/procd
會帶-h
的引數,當
procd
退出後會呼叫
exec執行
/sbin/proc
替換當前
init
程序(具體過程可參見
procd
程式包中的
init
和procd
程式)。這就是系統啟動完成後,
ps命令顯示
的程序號為
1的程序名最終為
/sbin/procd
的由來,中間是有幾次變化的。
繼續看/etc/preinit
指令碼,出來變數設定外,接下來是執行了三個
shell
指令碼:
. /lib/functions.sh
. /lib/functions/preinit.sh
. /lib/functions/system.sh
注意「.
」和「/
」之間是有空格的,這裡的點相當與
souce
命令,但
souce
是bash
特有的,並不在
posix
標準中,「.」
是通用的用法。使用「
.」的意思是在當前
shell
環境下執行,並不會在子
shell
中執行。這幾個
shell
指令碼主要定義了
shell
函式,
特別是preinit.sh
中,定義了
hook
相關操作的函式。
之後會使用boot_hook_init
定義五個
hook
結點如下:
boot_hook_init preinit_essential
boot_hook_init preinit_main
boot_hook_init failsafe
boot_hook_init initramfs
boot_hook_init preinit_mount_root
之後會向這些結點中新增hook
函式。
在之後就是乙個迴圈,依次在當前shell
下執行/lib/preinit/
目錄下的指令碼,
for pi_source_file in /lib/preinit/*; do
. $pi_source_file
done
/lib/preinit/目錄下的指令碼具體類似的格式,定義要新增到
hook
結點的函式,然後通過
boot_hook_add
將該函式新增到
對應的hook
結點。
最後,/etc/preinit
就會執行
boot_run_hook
函式執行對應
hook
結點上的函式。在當前環境下只執行了
preinit_essential和
preinit_main
結點上的函式,如下:
boot_run_hook preinit_essential
boot_run_hook preinit_main
到此,/etc/preinit
執行完畢並退出。如果需要跟蹤除錯這些指令碼,可以 在
/etc/preinit
的最開始新增一條命令
set -x,這
樣就會列印出執行命令的過程, 當並不會真正執行。
至於系統服務程式的啟動及初始化將全由procd
完成,procd
的功能不僅在於此,它還整合更多其他功能,具體可參見
procd
的資料。
1.openwrt啟動指令碼分析,
2.openwrt barrier break 14.07原始碼
**:
openwrt啟動流程
openwrt是通過一系列shell指令碼進行啟動流程的組織,下面是啟動流程的提綱。如 果想詳細了解啟動的過程,則需要仔細走讀指令碼檔案。1.在make menuconfig 選擇target平台 broadcom bcm947xx 953xx 2.4 2.linux核心的配置檔案由下面兩個檔案組成...
openwrt啟動流程
了解openwrt系統的啟動流程 1.1 系統介紹 任何系統的啟動都是開發人員首要關注的問題,因為只有了解了系統的啟動流程和啟動機制,才能真正掌握乙個系統,如果對系統的啟動不熟悉的話,是不可能用好乙個系統的。openwrt系統也不例外,他的啟動和一般的嵌入式系統的啟動還有所區別,下面記錄一下open...
OpenWrt啟動指令碼規則
在做專案過程中,時常新增一些啟動指令碼,但是對整個指令碼的啟動流程和規則缺乏理解,所以整理加深一下。etc init.d etc rc.d bin sh 指令碼直譯器 etc rc.common 指令碼執行前的檢查指令碼,可以檢測出非法的引數 start 40 在etc rc.d 生成s40 在啟動...