init是Linux系統操作中不可缺少的程序之一。 是一個由內核啓動的用戶級進程。
內核啓動(已經被載入內存,開始運行,並已初始化所有的設備驅動程序和數據結構等)之後,就通過啓動一個用戶級程序init的方式來啓動其他用戶級的進程或服務。所以,init始終是第一個進程(其PID始終爲1)。
內核會在過去曾使用過init的幾個地方查找它,它的正確位置(對Linux系統來說)是/sbin/init.如果內核找不到init,它就會試着運行/bin/sh,如果運行失敗,系統的啓動也會失敗。
二、運行級別
Runlevel 0是讓init關閉所有進程並終止系統。
Runlevel 2是允許系統進入多用戶的模式,但並不支持文件共享,這種模式很少應用。
Runlevel 3是最常用的運行模式,主要用來提供真正的多用戶模式,也是多數服務器的缺省模式。
Runlevel 4一般不被系統使用,用戶可以設計自己的系統狀態並將其應用到runlevel 4階段,儘管很少使用,但使用該系統可以實現一些特定的登錄請求。
Runlevel 5是將系統初始化爲專用的X Window終端。對功能強大的Linux系統來說,這並不是好的選擇,但用戶如果需要這樣,也可以通過在runlevel啓動來實現該方案。
Runlevel 6是關閉所有運行的進程並重新啓動系統。
The following runlevels are defined:
N System bootup (NONE).
S Single user mode (not to be switched to directly)
0 halt
1 single user mode
2 .. 5 multi user mode
6 reboot
這些級別在/etc/inittab 文件裏指定。這個文件是init 程序尋找的主要文件,最先運行的服務是放在/etc/rc.d 目錄下的文件。在大多數的Linux 發行版本中,啓動腳本都是位於 /etc/rc.d/init.d中的。這些腳本被用ln 命令連接到 /etc/rc.d/rcn.d 目錄。(這裏的n 就是運行級0-6)
三、運行級別的配置
在inittab文件中以#開頭的所有行都是註釋行。註釋行有助於用戶理解inittab文件,inittab文件中的值都是如下格式:
label:runlevel:action:process
id 用來定義缺省的init運行的級別
si 是系統初始化的進程
ln 其中的n從1~6,指明該進程可以使用的runlevel的級別
ud 是升級進程
ca 指明當按下Ctrl+Alt+Del時運行的進程
pf 指當UPS表明斷電時運行的進程
pr 是在系統真正關閉之前,UPS發出電源恢復的信號時需要運行的進程
x 是將系統轉入X終端時需要運行的進程
2,runlevel字段指定runlevel的級別。可以指定多個runlevel級別,也可以不爲runlevel字段指定特定的值。(另外sysinit、boot、bootwait這三個進程會忽略這個設置值。)
respawn:表示init應該監視這個進程,即使其結束後也應該被重新啓動。
wait:init應該運行這個進程一次,並等待其結束後再進行下一步操作。
once:init需要運行這個進程一次。
boot:隨系統啓動運行,所以runlevel值對其無效。
bootwait:隨系統啓動運行,並且init應該等待其結束。
off:沒有任何意義。
initdefault:系統啓動後的默認運行級別;由於進入相應的運行級別會激活對應級別的進程,所以對其指定process字段沒有任何意義。如果inittab文件內不存在這一條記錄,系統啓動時在控制檯上詢問進入的運行級。
sysinit:系統啓動時準備運行的命令。比如說,這個命令將清除/tmp.可以查看/etc/rc.d/rc.sysinit腳本瞭解其運行了那些操作。
powerwait:允許init在電源被切斷時,關閉系統。當然前提是有U P S和監視U P S並通知init電源已被切斷的軟件。RH linux默認沒有列出該選項。
powerfail:同powerwait,但init不會等待正在運行的進程結束。RH linux默認沒有列出該選項。
powerokwait:當電源監視軟件報告“電源恢復”時,init要執行的操作。
powerfailnow:檢測到ups電源即將耗盡時,init要執行的操作,和powerwait/powerfail不同的喲。
ctrlaltdel:允許init在用戶於控制檯鍵盤上按下Ctrl + Alt + Del組合鍵時,重新啓動系統。注意,如果該系統放在一個公共場所,系統管理員可將Ctrl + Alt + Del組合鍵配置爲別的行爲,比如忽略等。我是設置成打印一句罵人的話了^o^. kbrequest:監視到特定的鍵盤組合鍵被按下時採取的動作,現在還不完善。
ondemand:A process marked with an ondemand runlevel will be executed whenever the specified ondemand runlevel is called. However, no runlevel change will occur (ondemand runlevels are ‘a’, ‘b’,and ‘c’),(英語太菜,那個however不知道該怎麼翻譯纔好。慚愧!)
4,process字段包含init執行的進程,該進程採用的格式與在命令行下運行該進程的格式一樣,因此process字段都以該進程的名字開頭,緊跟着是運行時,緊跟着是運行時要傳遞給該進程的參數。比如/sbin/shutdown -t3 -r now,該進程在按下Ctrl+Alt+Del時執行,在命令行下也可以直接輸入來重新啓動系統。
四、例子
仔細學習例子文件,學習應用其中關於inittab的語法格式。該文件的大多數內容都可以忽略,因爲超過一半的內容都是註釋,剩餘的一些文件內容主要是用來實現某些特殊的功能:
id 的值表明缺省的runlevel是3。
ud 的值可以喚醒/sbin/update進程,該進程爲保持磁盤的完整性,將在對磁盤進行I/O操作之前清空整個I/O緩衝區。
pf、pr和ca的值只被特定的中斷所調用。
如果系統是專用的X終端,則只需x的輸入值。
getty進程來提供虛擬終端設備的服務,例如:
3:2345:respawn:/sbin/mingetty tty3
標籤字段的值是3,3是設備tty3的數字後綴,tty3與相應的進程相關聯,該getty進程可以啓動的runlevel是2、3、4和5,當該進程終止時,init馬上就重新啓動它。啓動進程的路徑名是/sbin/mingetty,該進程是實現虛擬終端支持的最小版本的getty,爲tty3提供啓動虛擬設備的進程。
si::sysinit:/etc/rc.d/rc.sysinit
該值告訴init程序運行/etc/rc.d/rc.sysinit腳本文件來初始化系統,該腳本文件與所有啓動的腳本類似,它只是一個包含Linux的 shell命令的可執行文件,注意輸入的字符串必須包括該腳本的完整路徑。不同版本的Linux存放該腳本的位置也不相同,但不用刻意去記憶這些位置,只需查看/etc/inittab文件即可,該文件中包含啓動腳本文件的確切位置。
另一篇文章介紹:
首先介紹點背景知識,關於inittab的:
init進程是系統中所有進程的父進程,init進程繁衍出完成通常操作所需的子進程,這些操作包括:設置機器名、檢查和安裝磁盤及文件系統、啓動系統日誌、配置網絡接口並啓動網絡和郵件服務,啓動打印服務等。Solaris中init進程的主要任務是按照inittab文件所提供的信息創建進程,由於進行系統初始化的那些進程都由init創建,所以init進程也稱爲系統初始化進程。
下面具體說明inittab文件的格式。
inittab文件中每一記錄都從新的一行開始,每個記錄項最多可有512個字符,每一項的格式通常如下:id:rstate:action:process,下面分別解釋。
1.id字段是最多4個字符的字符串,用來唯一標誌表項。
2.rstate(run
state)字段定義該記錄項被調用時的運行級別,rstate可以由一個或多個運行級別構成,也可以是空,空則代表運行級別0~6。當請求init改變運行級別時,那些rstate字段中不包括新運行級別的進程將收到SIGTERM警告信號,並且最後被殺死;只有a、b、c啓動的命令外(a、b、c不是真正的運行級別)
3.action字段告訴init執行的動作,即如何處理process字段指定的進程,action字段允許的值及對應的動作分別爲:
1)respawn:如果process字段指定的進程不存在,則啓動該進程,init不等待處理結束,而是繼續掃描inittab文件中的後續進程,當這樣的進程終止時,init會重新啓動它,如果這樣的進程已存在,則什麼也不做。
2)wait:啓動process字段指定的進程,並等到處理結束纔去處理inittab中的下一記錄項。
3)once:啓動process字段指定的進程,不等待處理結束就去處理下一記錄項。當這樣的進程終止時,也不再重新啓動它,在進入新的運行級別時,如果這樣的進程仍在運行,init也不重新啓動它。
4)boot:只有在系統啓動時,init才處理這樣的記錄項,啓動相應進程,並不等待處理結束就去處理下一個記錄項。當這樣的進程終止時,系統也不重啓它。
5)bootwait:系統啓動後,當第一次從單用戶模式進入多用戶模式時處理這樣的記錄項,init啓動這樣的進程,並且等待它的處理結束,然後再進行下一個記錄項的處理,當這樣的進程終止時,系統也不重啓它。
6)powerfail:當init接到斷電的信號(SIGPWR)時,處理指定的進程。
7)powerwait:當init接到斷電的信號(SIGPWR)時,處理指定的進程,並且等到處理結束纔去檢查其他的記錄項。
8)off:如果指定的進程正在運行,init就給它發SIGTERM警告信號,在向它發出信號SIGKILL強制其結束之前等待5秒,如果這樣的進程不存在,則忽略這一項。
9)ondemand:功能通respawn,不同的是,與具體的運行級別無關,只用於rstate字段是a、b、c的那些記錄項。
10)sysinit:指定的進程在訪問控制檯之前執行,這樣的記錄項僅用於對某些設備的初始化,目的是爲了使init在這樣的設備上向用戶提問有關運行級別的問題,init需要等待進程運行結束後才繼續。
11)initdefault:指定一個默認的運行級別,只有當init一開始被調用時才掃描這一項,如果rstate字段指定了多個運行級別,其中最大的數字是默認的運行級別,如果rstate字段是空的,init認爲字段是0123456,於是進入級別6,這樣便陷入了一個循環,如果
inittab文件中沒有包含initdefault的記錄項,則在系統啓動時請求用戶爲它指定一個初始運行級別
4.Process字段中進程可以是任意的守候進程、可執行腳本或程序。
另外:在任何時候,可以在文件inittab中添加新的記錄項,級別Q/q不改變當前的運行級別,重新檢查inittab文件,可以通過命令init
Q或init q使init進程立即重新讀取並處理文件inittab
以上這些都是介紹的標準的linux System V的標準,所以對嵌入式來講有些東西並不見得有用!這裏介紹點針對嵌入式的,也就是針對busybox init的:
busybox的init
除了基本的命令之外,BusyBox還支持init功能,如同其它的init一樣,busybox的init也是完成系統的初始化工作,關機前的工作等等,我們知道在Linux的內核被載入之後,機器就把控制權轉交給內核,linux的內核啓動之後,做了一些工作,然後找到根文件系統裏面的init程序,並執行它,BusyBox的init進程會依次進行以下工作:(參考<<構建嵌入式LINUX系統>> p201)
1. 爲init設置信號處理過程
2. 初始化控制檯
3. 剖析/etc/inittab文件
4. 執行系統初始化命令行,缺省情況下會使用/etc/init.d/rcS
5. 執行所有導致init暫停的inittab命令(動作類型:wait)
6. 執行所有僅執行一次的inittab(動作類型:once)
一旦完成以上工作,init進程便會循環執行以下進程:
1. 執行所有終止時必須重新啓動的inittab命令(動作類型:once)
2. 執行所有終止時必須重新啓動但啓動前必須詢問用戶的inittab命令(動作類型:askfirst)
初始化控制檯之後,BusyBox會檢查/etc/inittab文件是否存在,如果此文件不存在,BusyBox會使用缺省的inittab配置,它主要爲系統重引導,系統掛起以及init重啓動設置缺省的動作,此外它還會爲四個虛擬控制檯(tty1到tty4)設置啓動shell的動作。如果未建立這些設備文件,BusyBox會報錯。
inittab文件中每一行的格式如下所示:(busybox的根目錄下的example文件夾下有詳盡的inittab文件範例)
id:runlevel:action:process
儘管此格式與傳統的Sytem V init類似,但是,id在BusyBox的init中具有不同的意義。對BusyBox而言,id用來指定啓動進程的控制tty。如果所啓動的進程並不是可以交互的shell,例如BusyBox的sh(ash),應該會有個控制tty,如果控制tty不存在,Busybox的sh會報錯。BusyBox將會完全忽略runlevel字段,所以空着它就行了,你也許會問既然沒用保留着它幹嗎,我想大概是爲了和傳統的Sytem V init保持一致的格式吧。process字段用來指定所執行程式的路徑,包括命令行選項。action字段用來指定下面表中8個可應用到process的動作之一。
動作
結果
sysinit
爲init提供初始化命令行的路徑
respawn
每當相應的進程終止執行便會重新啓動
askfirst
類似respawn,不過它的主要用途是減少系統上執行的終端應用程序的數量。它將會促使init在控制檯上顯示“Please
press Enter to active this
console”的信息,並在重新啓動之前等待用戶按下enter鍵
wait
告訴init必須等到相應的進程完成之後才能繼續執行
once
僅執行相應的進程一次,而且不會等待它完成
ctratldel
當按下Ctrl+Alt+Delete組合鍵時,執行相應的進程
shutdown
當系統關機時,執行相應的進程
restart
當init重新啓動時,執行相應的進程,通常此處所執行的進程就是init本身
以下是我的usblinux的inittab文件
::sysinit:/etc/init.d/rcS
::respawn:/sbin/getty 115200 tty1
tty2::askfirst:-/bin/sh
tty3::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/bin/umount -a -r
這個inittab執行下列動作
1. 將/etc/init.d/rcS設置成系統的初始化文件
2. 在115200 bps的虛擬終端tty1上啓動一個登陸會話 (注意getty的用法)
3. 在虛擬終端tty2和tty3上啓動askfirst動作的shell
4. 如果init重新啓動,將/sbin/init設置成它會執行的程序
5. 告訴init,在系統關機的時候執行umount命令卸載所有文件系統,並且在卸載失敗時用只讀模式衝新安裝以保護文件系統。
1、busybox的inittab與pc使用的inittab不同,第一ID並不是隨便取名字的,這個名字要與/dev/目錄下是否有對應的文件對應
對應錯誤
can't open /dev/0: No such file or directory
process '-/bin/sh' (pid 789) exited. Scheduling for restart.
can't open /dev/0: No such file or directory
process '-/bin/sh' (pid 793) exited. Scheduling for restart.
2、出現下面這種錯誤:
process '-/bin/sh' (pid 789) exited. Scheduling for restart.
process '-/bin/sh' (pid 794) exited. Scheduling for restart.
process '-/bin/sh' (pid 796) exited. Scheduling for restart.
process '-/bin/sh' (pid 798) exited. Scheduling for restart.
對應的inittab文件中有
ttyS0::askfirst:-/bin/sh
雖然在/dev/目錄下有ttyS0設備,但是這個設備顯然不可用,所以纔會出現上面的錯誤
3、當在inittab中同時定義的兩個在同一個串口終端登陸的語句時
::askfirst:-/bin/sh
s3c2410_serial0:23456:respawn:/sbin/getty -L s3c2410_serial0 115200 vt100
出現的情況就是被搶佔,不能接收任何串口輸入
4、bad inittab entry
多半時因爲非法字符造成的。
5、busybox中的字段runleve也沒有運行時的運行級別的概念
6、分析一下啓動的過程
1. 爲init設置信號處理過程
2. 初始化控制檯
3. 剖析/etc/inittab文件
4. 執行系統初始化命令行,缺省情況下會使用/etc/init.d/rcS
5. 執行所有導致init暫停的inittab命令(動作類型:wait)
6. 執行所有僅執行一次的inittab(動作類型:once)
一旦完成以上工作,init進程便會循環執行以下進程:
1. 執行所有終止時必須重新啓動的inittab命令(動作類型:once)
2. 執行所有終止時必須重新啓動但啓動前必須詢問用戶的inittab命令(動作類型:askfirst)
初始化控制檯之後,BusyBox會檢查/etc/inittab文件是否存在,如果此文件不存在,BusyBox會使用缺省的inittab配置,它主要爲系統重引導,系統掛起以及init重啓動設置缺省的動作,此外它還會爲四個虛擬控制檯(tty1到tty4)設置啓動shell的動作。如果未建立這些設備文件,BusyBox會報錯。
7、網上有人問“-”的作用
我很納悶:
:: respawn:-/bin/sh
這個-是幹什麼的,爲什麼有的時候有有的時候沒有???
還有啊,我從網上看到一個例程,如下,節選:
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
我搞不清兩個的區別,這樣控制檯就啓動了,是第一句啓動的還是第二句,那我內核啓動參數裏面的console=ttyS0會自動來找這個控制檯???
原帖由 wavezone 於 2008-8-22 16:34 發表
我很納悶:
:: respawn:-/bin/sh
這個-是幹什麼的,爲什麼有的時候有有的時候沒有???
還有啊,我從網上看到一個例程,如下,節選:
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
我搞不清兩個的區別 ...
測試的時候是這樣的,加上”-”的語句會在登陸終端之後調用/etc/目錄下的profile文件,而不加”-”的不會執行這個腳本。
其實登陸終端的命令有幾種方便,但是標準的還是使用getty來登陸,但是直接使用如上的語句也是可以的,並且兼容性強一點,因爲它不需要指定對應的串口設備。
::askfirst:-/bin/sh
s3c2410_serial0::askfirst:-/bin/sh
::askfirst:-/bin/sh
s3c2410_serial0:23456:respawn:/sbin/getty -L s3c2410_serial0 115200 vt100
都是可用的。
8./bin/sh: XXX not found
arm-linux-readelf -d xxx
查看你的以用程序依賴哪些庫
一般是因爲缺少libc.so.6造成的,實際還是根文件系統的問題,沒有將常用的庫文件拷貝到/lib目錄下
常用的庫:
[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/ld* .
[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/libc-2.3.2.so .
[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/libc.so.6 .
[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/libm * .
[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/libcrypt* .
9、錯誤insmod: chdir(2.6.26.6): No such file or directory
網上有人提出這種解決方法:
需要注意的是insmod等模塊加載命令需要從lib/modules/2.6.26.6
的目錄下加載模塊,所以必須先建立此目錄,然後將模塊放到此目錄下面,否則將出現以下兩種情況:
一是沒有建立lib/modules/2.6.26.6目錄,取決於內核版本號,將出現insmod: chdir(2.6.26.6): No such file or directory的錯誤
二是隻將模塊簡單地放在根目錄或其它文件夾,沒有將其拷貝到指定的lib/modules/2.6.26.6目錄,將出現
insmod: module 'gpio_driver' not found錯誤
不過這種方法不是很奏效
根本原因是insmod的問題,在busybox編譯的時候參考下面的選項,不要使用
Linux Module Utilities --->
[ ] Simplified modutils
//該選項不要選擇
[*] Support version 2.6.x Linux kernels
//此選項選上
參考如下:
10、不能執行”-h”命令
在執行xxx –h時沒有任何反應。是在lib目錄下缺少常見的庫文件
參考如下:
[root@vm-dev rootfs]# ls lib/
ld-2.3.6.so libc-2.3.6.so libgcc_s.so libnsl.so.1 libnss_files.so.2 libnss_nis.so.2 librt-2.3.6.so libthread_db.so.1
ld-linux.so.2 libcrypt-2.3.6.so libgcc_s.so.1 libnss_compat-2.3.6.so libnss_hesiod-2.3.6.so libpcprofile.so librt.so.1 libutil-2.3.6.so
libanl-2.3.6.so libcrypt.so.1 libm-2.3.6.so libnss_compat.so.2 libnss_hesiod.so.2 libpthread-0.10.so libSegFault.so libutil.so.1
libanl.so.1 libc.so.6 libmemusage.so libnss_dns-2.3.6.so libnss_nis-2.3.6.so libpthread.so.0 libtermcap.so.2 modules
libBrokenLocale-2.3.6.so libdl-2.3.6.so libm.so.6 libnss_dns.so.2 libnss_nisplus-2.3.6.so libresolv-2.3.6.so libtermcap.so.2.0.8
libBrokenLocale.so.1 libdl.so.2 libnsl-2.3.6.so libnss_files-2.3.6.so libnss_nisplus.so.2 libresolv.so.2 libthread_db-1.0.so
一份完整的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