Linux作業系統中/sbin/init程式的執行過程

來源:互聯網
上載者:User

當init啟動後,它通過執行
各種啟動事務來繼續引導進程(檢查並監視檔案系統,啟動背景程式daemons,等等),直至完成使用者所有作業環境的設定工作。這裡主要涉及4個程
序:init、getty(agetty)、login和shell程式。這4個程式之間的關係見所示。

 

init進程的主要任務是根據/etc/rc檔案中設定的資訊,執行其中設定的命
令,然後根據/etc/inittab檔案中的資訊,為每一個允許登入的終端裝置使用fork()建立一個子進程,並在每個新建立的子進程中運行
agetty
(getty)程式。而init進程則調用wait(),進入等待子進程結束狀態。每當它的一個子進程結束退出,它就會根據wait()返回的pid號知
道是哪個對應終端的子進程結束了,因此就會為相應終端裝置再建立一個新的子進程,並在該子進程中重新執行agetty程式。這樣,每個被允許的終端裝置都
始終有一個對應的進程為其等待處理。

在正常的操作下,init確定agetty正在工作著以允許使用者登入,並且收取孤
立進程。孤立進程是指那些其父輩進程已結束的進程;在Linux中所有的進程必須屬於單棵進程樹,所以孤立進程必須被收取。當系統關閉時,init負責殺
死所有其它的進程,卸載所有的檔案系統以及停止處理器的工作,以及任何它被配置成要做的工作。

 

getty程式的主要任務是設定終端類型、屬性、速度和線路規程。它開啟並初始化一
個tty連接埠,顯示提示資訊,並等待使用者鍵入使用者名稱。該程式只能由超級使用者執行。通常,若/etc/issue文字檔存在,則getty會首先顯示其中
的文本資訊,然後顯示登入提示資訊(例如:plinux login: ),讀取使用者鍵入的登入名稱,並執行login程式。

為了能讓init程式運行getty,/etc/inittab檔案中必須含有getty(agetty)命令。/etc/inittab檔案中有關agetty的內容例子見如下所示。

 

列表 3.1 poeigl-1.2中的inittab檔案

# inittab for linux, poeigl 1.2

# format:

# ttyline:termcap-entry:getty-command

tty1:con80x60:/bin/agetty 9600 tty1

tty2:con80x60:/bin/agetty 9600 tty2

tty3:con80x60:/bin/agetty 9600 tty3

tty4:con80x60:/bin/agetty 9600 tty4

# tty5:con80x60:/bin/agetty 9600 tty5

# tty64:dumb:/bin/agetty 9600 tty64

# tty65:dumb:/bin/agetty -m -t60 2400 tty65

 

每個終端都有自己的getty命令。其中列出了tty1—tty4對應的登入項信
息。以’#’開始的是注釋行。第1列是所用終端裝置名稱,第2列是指定終端的類型,這裡指定了終端類型是con80x60。第3列是所執行的命令及其參
數。最後兩行中的tty64和tty65對應串連在序列埠上的終端。

對於使用序列埠與主機直接相連的終端以及通過modem撥號連線的終
端,Linux的agetty程式還有其它一些屬性。如在讀取登入名稱時自動調整tty的設定資訊,例如同位位元、檫除字元、行結束字元以及上檔鍵字元
等。可選擇地從連結的Hayes相容modem資訊中檢測出傳輸傳輸速率。

/dev/inittab中每一項的參數格式與具體使用哪一種getty程式有關。目前一般常用的getty程式有如下幾種:

 

1.agetty(有時直接稱為getty):容易設定,無須設定檔。適用於直接連接的終端;

2.getty(getty_ps的一部分):適用於直接連接的終端;

3.mgetty:最適合於通過modem串連,也可用於直連;

4.uugetty:僅用於通過modem串連終端,是getty_ps軟體包的部分;

5.mingetty:簡單的getty。適用於控制台終端或虛擬終端;

6.fbgetty:適用於控制台或虛擬終端。

Redhat 9系統預設配置中帶有mingetty和agetty兩個程式。控制台或虛擬終端使用的是mingetty。對於實際的字元終端則一般使用agetty。因此在Redhat 9系統的/etc/inittab檔案中會看到以下的資訊。

 

列表 3.2 RedHat 9系統的/etc/inittab檔案中有關getty的資訊

# Run gettys in standard runlevels

1:2345:respawn:/sbin/mingetty tty1

2:2345:respawn:/sbin/mingetty tty2

3:2345:respawn:/sbin/mingetty tty3

4:2345:respawn:/sbin/mingetty tty4

5:2345:respawn:/sbin/mingetty tty5

6:2345:respawn:/sbin/mingetty tty6

 

其中第1列表示名稱tty後的數字,2345表示該mingetty的運行層。respawn表示如果該mingetty被終止,則mingetty將再次自動執行。/sbin/mingetty是命令。ttyn代表/dev/ttyn(n表示數字1—5)。

在登入到Linux系統中之後,你會發現(使用”top”或”ps –ax”命令)自己終端原來的getty進程已經找不到了。因為getty進程執行了login程式,被替換成了login進程,並且最後被替換成你的登入shell進程。

 

當你在”login:
“提示符下鍵入了你的使用者名稱後,getty會讀取使用者名稱並且去執行login程式,也把使用者名稱資訊傳給了它。因此getty進程被替換成了login進
程。此時login進程會接著要求你輸入口令。在口令檢查通過後就會去執行/etc/passwd檔案中對應你使用者名稱項中記錄的程式。通常這個程式是
bash shell程式。因此原來的getty進程最終被替換成了bash進程,對應的這三個程式也就都具有相同的進程ID。

 

當登出登入(log
out)時,則該終端上的所有進程都會被終止(killed),包括登入shell進程bash。因此,對於在/etc/inittab檔案中列出的
getty程式,一旦其被替換執行的bash程式被終止或退出,init進程就會為對應終端重新建立一個getty進程。

 

login程式則主要用於要求登入使用者輸入密碼。根據使用者輸入的使用者名稱,它從口令文
件passwd中取得對應使用者的登入項,然後調用getpass()以顯示”password:”提示資訊,讀取使用者鍵入的密碼,然後使用密碼編譯演算法對鍵入
的密碼進行加密處理,並與口令檔案中該使用者項中pw_passwd欄位作比較。如果使用者幾次鍵入的密碼均無效,則login程式會以出錯碼1退出執行,表
示此次登入過程失敗。此時父進程(進程init)的wait()會返回該退出進程的pid,因此會根據記錄下來的資訊再次建立一個子進程,並在該子進程中
針對該終端裝置再次執行agetty程式,重複上述過程。

 

login程式也可以被使用者在運行過程中在shell下當作一個命令執行。此時它可
以被用隨時從一個使用者切換成另一個使用者。如果執行時沒有給出參數,則login就會顯示輸入使用者名稱的提示資訊。如果使用者不是超級使用者(root),並且
/etc/目錄下存在一個名為nologin的檔案,那麼該檔案中的資訊就會被顯示出來,此次登入過程也隨即被終止。

 

如果在/etc/usertty檔案中對該使用者指定了特殊的訪問限制,那麼這些限制要求必須滿足。如果是一個超級使用者,那麼所使用的登入tty裝置必須是在/etc/securetty檔案中指定的。

 

在所有這些條件滿足之後,login同樣也會要求使用者輸入密碼並對其進行檢查。如
果.hushlogin存在的話,login就會執行一個“安靜”的登入過程,也即不檢查是否有郵件,也不顯示上次登入時間和motd檔案中的資訊。否則
如果/var/log/lastlog檔案存在的話,就會顯示其中的最後登入時間。

 

如果使用者鍵入的密碼正確,則login就會把當前工作目錄(Currend
Work
Directory)修改成口令檔案中指定的該使用者的起始工作目錄。並把對該終端裝置的存取權限修改成使用者讀/寫和組寫,設定進程的組ID。然後利用所得
到的資訊初始化環境變數資訊,例如起始目錄(HOME=)、使用的shell程式(SHELL=)、使用者名稱(USER=和LOGNAME=)和系統執行程
序的預設路徑序列(PATH=)。接著顯示/etc/motd檔案(message-of-the-day)中的文本資訊,並檢查並顯示該使用者是否有郵件
的資訊。最後login程式改變成登入使用者的使用者ID並執行口令檔案中該使用者項中指定的shell程式,如bash或csh等。

 

如果口令檔案/etc/passwd中該使用者項中沒有指定使用哪個shell程式,
系統則會使用預設的/bin/sh程式。如果口令檔案中也沒有為該使用者指定使用者起始目錄的話,系統就會使用預設的根目錄/。有關login程式的一些執行
選項和特殊訪問限制的說明,請參見Linux系統中的線上手冊頁(man 8 login)。

 

Shell程式是一個複雜的命令列解釋程式,是當使用者登入系統進行互動操作時執行的
程式。它是使用者與電腦進行互動操作的地方。它擷取使用者輸入的資訊,然後執行命令。使用者可以在終端上向shell直接進行互動輸入,也可以使用shell
指令檔向shell解釋程式輸入。在Linux系統中,目前常用的shell有:

 

Bourne Again Shell,/bin/bash

C shell,/bin/csh(或tcsh)

BSD shell/bin/ash(或bsh)

在登入過程中,系統(login)會從口令檔案使用者對應登入項的最後一個欄位知道應該為使用者執行哪個shell程式。

 

shell程式中實現了一個具有流量控制結構的語言,使用相當廣泛。目前這些
shell程式都朝著與IEEE POSIX
1003.2相容的方向發展,因此它們各自雖然各自有自己的特點,但準系統已經越來越相象。本書主要介紹bash的工作原理和實現機制,其它幾種
shell的實現機制與之類似。

 

在登入過程中login開始執行shell時,所帶參數argv[0]的第一個字元
是’-’,表示該shell是作為一個登入shell被執行。此時該shell程式會根據該字元,執行某些與登入過程相應的操作。登入shell會首先從
/etc/profile檔案以及.profile檔案(若存在的話)讀取命令並執行。如果在進入shell時設定了ENV環境變數,或者在登入
shell的.profile檔案中設定了該變數,則shell下一步會從該變數命名的檔案中讀去命令並執行。因此使用者應該把每次登入時都要執行的命令放
在.profile檔案中,而把每次運行shell都要執行的命令放在ENV變數指定的檔案中。設定ENV環境變數的方法是把下列語句放在你起始目錄
的.profile檔案中。

 

ENV=$HOME/.anyfilename; export ENV

 

在執行shell時,除了一些指定的可選項以外,如果還指定了命令列參數,則shell會把第一個參數看作是一個指令檔名並執行其中的命令,而其餘的參數則被看作是shell的位置參數($1、$2等)。否則shell程式將從其標準輸入中讀取命令。

 

在執行shell程式時可以有很多選項,請參見Linux系統中的有關sh的線上手冊頁中的說明。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.