天天看點

linux成為init子程序,Linux初始化程序(init)

初始化程序(init)

“Uuno on numero yksi”(Slogan for a series of Finnish movies.)

本章描述init程序,它是核心啟動的第一個使用者級程序。init有許多很重要的任務,比如象啟動getty(用于使用者登入)、實作運作級别、以及處理孤立程序。本章解釋了怎樣配置init以及如何運用不同的運作級别。

第一步init

對于Linux系統的運作來說,init程式是最基本的程式之一。但你仍可以大部分的忽律它。一個好的Linux發行版本通常随帶有一個init的配置,這個配置适合于絕大多數系統的工作,在這樣一些系統上不需要對init做任何事。通常,隻有你在碰到諸如串行終端挂住了、撥入(不是撥出)數據機、或者你希望改變預設的運作級别時你才需要關心init。

當核心啟動了自己之後(已被裝入記憶體、已經開始運作、已經初始化了所有的裝置驅動程式和資料結構等等),通過啟動使用者級程式init來完成引導程序的核心部分。是以,init總是第一個程序(它的程序号總是1)。

核心在幾個位置上來查尋init,這幾個位置以前常用來放置init,但是init的最适當的位置(在Linux系統上)是/sbin/init。如果核心沒有找到init,它就會試着運作/bin/sh,如果還是失敗了,那麼系統的啟動就宣告失敗了。

當init開始運作,它通過執行一些管理任務來結束引導程序,例如檢查檔案系統、清理/tmp、啟動各種服務以及為每個終端和虛拟控制台啟動getty,在這些地方使用者将登入系統(見第八章)。

在系統完全起來之後,init為每個使用者已退出的終端重新開機getty(這樣下一個使用者就可以登入)。init同樣也收集孤立的程序:當一個程序啟動了一個子程序并且在子程序之前終止了,這個子程序立刻成為init的子程序。對于各種技術方面的原因來說這是很重要的,知道這些也是有好處的,因為這便于了解程序清單和程序樹圖。[1] init的變種很少。絕大多數Linux發行版本使用sysinit(由Miguel van Smoorenburg著),它是基于System V的init設計。UNIX的BSD版本有一個不同的init。最主要的不同在于運作級别:System V有而BSD沒有(至少是傳統上說)。這種差別并不是主要的。在此我們僅讨論sysvinit。

配置init以啟動getty:/etc/inittab檔案

當init啟動後,init讀取/etc/inittab配置檔案。當系統正在運作時,如果發出HUP信号,init會重讀它;[2]這個特性就使得對init的配置檔案作過的更改不需要再重新啟動系統就能起作用了。

/etc/inittab檔案有點複雜。我們将從配置getty行的簡單情況說起。etc/inittab中的行由四個冒号限定的域組成:

id:runlevels:action:process

下面對各個域進行了描述。另外,/etc/inittab可以包含空行以及以數字元号(’#’)開始的行;這些行均被忽略。

id

這确定檔案中的一行。對于getty行來說,指定了它在其上運作的終端(裝置檔案名/dev/tty後面的字元)。對于别的行來說,是沒有意義的(除了有長度的限制),但它必須是唯一的。

runlevels

該行應考慮的運作級别。運作級别以單個數字給出,沒有分隔符。(運作級别在下一節中讨論。)

action

對于該行應采取的動作,也即,respawn再次運作下一個域中的指令,當它存在時,或者僅運作一次。

process

要運作的指令。

為了在第一個虛拟終端上(/dev/tty1)運作getty、在所有的正規多使用者運作級别中(2-5),應該寫入下面這行:

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

第一個域指出這是對應于/dev/tty1的行。第二個域說明它應用于運作級别2,3,4和5。第三個域是說在指令退出之後,應被再次執行(是以,使用者可以登入、退出并且再次登入)。最後一個域是在第一個虛拟終端上運作getty的指令。[3]

如果你需要給系統增加終端或者撥入數據機線路,你應該給/etc/inittab增加更多的行,每一行對應一個終端或一條撥入線。詳細資訊,參見init、inittab以及getty的manual page。

如果一個指令運作時失敗了,并且init配置成重運作它,它會使用許多的系統資源:init運作它、它失敗了、init再運作它、再次失敗等等,沒完沒了。為了避免這樣,init将追蹤一個指令重運作了多少次,并且如果重運作的頻率太高,它将被延時五分鐘後再運作。

一個運作級别(run level)是init以及整個系統的狀态,它定義了能夠提供什麼系統服務。運作級别用數字來定義,見表7-1。對于如何使用使用者定義運作級别(2到5)沒有一緻的意見。有些系統管理者使用運作級别來定義哪個子系統工作,也即,X是否能運作、網絡是否能工作等等。其他人總是讓所有子系統工作着或者單獨地運作以及停止它們,而不改變它們的運作級别,因為運作級别對于控制他們的系統來說顯得太粗率了。你必須自己決定,但是按照你的Linux發行版本的做法來做也許是最容易的了。

表7-1.運作級别數

終止系統

1

單使用者模式(用于特别管理)

2-5

正常操作(使用者定義)

6

重新開機動

運作級别通過如下行所示的行在/etc/inittab中配置:

l2:2:wait:/etc/init.d/rc 2

第一個域是任意給的符号,第二個域指出是運作級别2。第三個域說明當進入該運作級别時,init應該運作第四個域中的指令一次,并且init應該等待它的結束。在進入運作級别2時,在需要時/etc/init.d/rc指令運作或者停止服務。

第四個域中的指令做所有設定一個運作級别的艱巨工作。它啟動還沒有運作的服務,并且停止在新的運作級别中不應再運作的服務。确切的指令是什麼以及運作級别是如何配置的,依賴于各個Linux發行版本。

當init開始運作時,它在/etc/inittab中查尋一行,該行指定了預設的運作級别:

id:2:initdefault:

通過給核心一個single或emergency指令行參數,你可以在init運作開始時轉到一個非預設的運作級别上。例如,核心指令行參數可以通過LILO給出。這使得你可以選擇單使用者模式(運作級别1)。

當系統正在運作時,telinit指令可以改變運作級别。當運作級别改變時,init就運作/etc/inittab中相應的指令。

/etc/inittab中的特殊配置

/etc/inittab有些特殊的特性,它允許init對特别的環境作出響應。這些與衆不同的特性在第三個域中由關鍵字标出。一些例子如下:

powerwait

當系統電源失敗時,允許init關閉系統。這裡假設使用了UPS以及用于監視UPS和通知init電源失敗的軟體。

ctrlaltdel

當使用者在控制台上按了ctrl-alt-del組合鍵時,允許init重新(啟動)引導系統。注意,系統管理者能夠配置對ctrl-alt-del組合鍵的響應為其它的什麼,例如,忽略它,如果系統是在一個公共的環境中(或者開始nethack。)

sysinit

當系統引導時要執行的指令。例如,這個指令通常是清理/tmp。

上面所列并不是全部。對于所有的關鍵字以及如何使用它們請參見inittab的manual page。

啟動(引導)進入單使用者模式

一個很重要的運作級别是單使用者模式(single user mode)(運作級别1),在這個模式中隻有系統管理者在使用機器并且隻有很少的系統服務在運作,如登入服務。對于一些管理任務來說單使用者模式是必須的,[4]如在/usr分區上運作fsck,因為這需要該分區沒被加載,除非幾乎所有的系統服務都被終止了,否則不可能會有這種情況。

通過telinit請求運作級别1,一個運作着的系統可以轉換到單使用者模式。在啟動時,可以通過在核心的指令行上給出single或emergency來進入單使用者模式:核心同樣也将指令行給init,init會了解那個單詞并且不會使用預設的運作級别。(核心指令行輸入的方法依賴于系統是如何引導的。)

在加載檔案系統之前,引導進入單使用者模式有時是需要的,這樣就可以手工運作fsck指令了,否則的話很可能損壞/usr分區(在一個有問題的檔案系統上的任何操作會更進一步地損壞它,是以fsck要盡早地運作)。

如果啟動時fsck的自動檢查失敗了,啟動描述檔案init就會自動地進入單使用者模式。這是試圖避免系統使用一個檔案系統,這個檔案系統損壞的太嚴重以至于fsck都不能夠自動地修複它。這樣的毀壞情況是相當少的,通常是硬碟有問題或是在試驗一個核心版本,但是有準備總比沒有好。

作為一個安全措施,一個正确配置的系統應該在運作單使用者模式的shell之前要求密碼。否則的話,隻要給LILO輸入适當的一行參數就很容易地以root身份進入系統。(當然,如果由于檔案系統的問題而使/etc/passwd毀壞時,就不是這樣了。如果是這樣的話,你手頭最好有張引導軟碟。)

注釋

init本身不允許終止。即使使用SIGKILL也不能終止init。

例如,作為root,使用指令kill –HUP 1。

不同版本的getty運作起來不同。參見manual page,并确定這是正确的manual page。

它通常不應用于使用nethack。