首頁/ 汽車/ 正文

Linux初始化init系統

近年來,

Linux

系統的

init

程序經歷了兩次重大的演進,傳統的

sysvinit

已經淡出歷史舞臺,新的

init

系統

UpStart

systemd

各有特點,而越來越多的

Linux

發行版採納了

systemd

。本文簡要介紹了這三種

init

系統的使用和原理,每個

Linux

系統管理員和系統軟體開發者都應該瞭解它們,以便更好地管理系統和開發應用。

Linux初始化init系統

Linux初始化init系統

1。 init 系統簡單介紹

Linux 作業系統的啟動首先從 BIOS 開始,接下來進入 boot loader,由 bootloader 載入核心,進行核心初始化。核心初始化的最後一步就是啟動 pid 為 1 的 init 程序,這個程序是系統的第一個程序,它負責產生其他所有使用者程序。

init 的一些特點

init

以守護程序方式存在,是所有其他程序的祖先。

init

程序非常獨特,能夠完成其他程序無法完成的任務。

init

系統能夠定義、管理和控制

init

程序的行為。它負責組織和執行許多獨立的或相關的始化工作(因此被稱為

init

系統),從而讓計算機系統進入某種使用者預訂的執行模式。

僅僅將核心執行起來是毫無實際用途的,必須由

init

系統將系統代入可操作狀態。比如啟動外殼

shell

後,便有了人機互動,這樣就可以讓計算機執行一些預訂程式完成有實際意義的任務。

init 的歷史及發展

大多數

Linux

發行版的

init

系統是和

System V

相相容的,被稱為

sysvinit

。這是人們最熟悉的

init

系統。一些發行版如 Slackware 採用的是 BSD 風格 Init 系統,這種風格使用較少,本文不再涉及。其他的發行版如 Gentoo 是自己定製的。Ubuntu 和 RHEL 採用

upstart

替代了傳統的 sysvinit。而 Fedora 從版本 15 開始使用了一個被稱為

systemd

的新 init 系統。

在 Linux 主要應用於

伺服器

PC

機的時代,SysVinit 執行非常良好,概念簡單清晰。它主要依賴於 Shell 指令碼,這就決定了它的

最大弱點:啟動太慢

。在很少重新啟動的 Server 上,這個缺點並不重要。而當 Linux 被應用到移動終端裝置的時候,啟動慢就成了一個大問題。為了更快地啟動,人們開始改進 sysvinit,先後出現了

upstart

systemd

這兩個主要的新一代 init 系統。Upstart 已經開發了 8 年多,在不少系統中已經替換 sysvinit。

Systemd

出現較晚,但發展更快,大有取代 upstart 的趨勢。

2。 sysvinit 的特點和使用

sysvinit

就是

system V

風格

的 init 系統,顧名思義,它源於 System V 系列 UNIX。它提供了比

BSD

風格

init 系統更高的靈活性。是已經風行了幾十年的

UNIX init

系統,一直被各類 Linux 發行版所採用。

2。1 sysvinit 執行級別

Sysvinit 用術語

runlevel

來定義預訂的執行模式

Sysvinit 檢查

/etc/inittab

檔案中是否含有

initdefault

這告訴

init

系統是否有一個預設執行模式,如果沒有預設的執行模式,那麼使用者將進入系統控制檯,手動決定進入何種執行模式

cat /etc/inittab# Default runlevel。 The runlevels used are:# 0 - halt (Do NOT set initdefault to this)# 1 - Single user mode# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)# 3 - Full multiuser mode# 4 - unused# 5 - X11# 6 - reboot (Do NOT set initdefault to this)id:3:initdefault:

2。2 sysvinit 執行順序

Sysvinit 巧妙地用指令碼、檔案命名規則和軟連結來實現不同的 runlevel 級別。

第一步

首先,

sysvinit

需要讀取

/etc/inittab

檔案

分析這個檔案的內容,它獲得以下一些配置資訊

系統需要進入的

runlevel

捕獲組合鍵的定義

定義電源

fail/restore

指令碼

啟動

getty

虛擬控制檯

第二步

得到配置資訊後,

sysvinit

順序地執行以下這些步驟,從而將系統初始化為預訂的

runlevel X

/etc/rc。d/rc。sysinit

/etc/rc。d/rc

/etc/rc。d/rcX。d/

(X 代表執行級別 0-6)

/etc/rc。d/rc。local

X Display Manager

(如果需要的話)

執行第二步解析

-

/etc/rc。d/rc。sysinit

首先,執行

rc。sysinit

以便執行一些重要的系統初始化任務

在 RedHat 公司的 RHEL5 中(RHEL6 已經使用

upstart

了),

rc。sysinit

主要完成以下這些工作

啟用

udev

selinux

設定定義在

/etc/sysctl。conf

中的核心引數

設定

系統時鐘

載入

keymaps

使能

交換分割槽

設定主機名(

hostname

分割槽檢查

remount

啟用

RAID

LVM

裝置

開啟

磁碟配額

檢查並掛載所有

檔案系統

清除過期的

locks

PID

檔案

/etc/rc.d/rc 和/etc/rc.d/rcX.d/

完成了以上這些工作之後,

sysvinit

開始執行

/etc/rc。d/rc

指令碼

根據不同的

runlevel

rc 指令碼

將開啟對應該

runlevel

rcX。d

目錄(

X

就是

runlevel

),找到並執行存放在該目錄下的所有啟動指令碼

每個

runlevel X

都有一個這樣的目錄,目錄名為

/etc/rc。d/rcX。d

/etc/rc。d/rcX。d

存放著很多不同的指令碼

檔名以

S

開頭的指令碼就是啟動時應該執行的指令碼,

S

後面跟的數字定義了這些指令碼的執行順序

檔名以

K

開頭的指令碼就是啟動時應該關閉的指令碼,

K

後面跟的數字定義了這些指令碼的執行順序

/etc/rc。d/rcX。d

目錄下的指令碼其實都是一些軟連結檔案,真實的指令碼檔案存放在

/etc/init。d

目錄下

# ll /etc/rc5。d/lrwxrwxrwx 1 root root 16 Sep 4 2008 K02dhcdbd -> 。。/init。d/dhcdbd。。。。(中間省略)。。。。lrwxrwxrwx 1 root root 14 Sep 4 2008 K91capi -> 。。/init。d/capilrwxrwxrwx 1 root root 23 Sep 4 2008 S00microcode_ctl -> 。。/init。d/microcode_ctllrwxrwxrwx 1 root root 22 Sep 4 2008 S02lvm2-monitor -> 。。/init。d/lvm2-monitor。。。。(中間省略)。。。。lrwxrwxrwx 1 root root 17 Sep 4 2008 S10network -> 。。/init。d/network。。。。(中間省略)。。。。lrwxrwxrwx 1 root root 11 Sep 4 2008 S99local -> 。。/rc。locallrwxrwxrwx 1 root root 16 Sep 4 2008 S99smartd -> 。。/init。d/smartd。。。。(底下省略)。。。。

/etc/rc.d/rc.local

當所有的初始化指令碼執行完畢,

sysvinit

執行

/etc/rc。d/rc。local

指令碼

rc。local

Linux

留給使用者進行個性化設定的地方

可以把自己私人想設定和啟動的東西放到這裡,一臺

Linux Server

的使用者一般不止一個,所以才有這樣的考慮

2。3 sysvinit 系統關閉

Sysvinit

不僅需要負責初始化系統,還需要負責關閉系統。在系統關閉時,為了保證資料的一致性,需要小心地按順序進行結束和清理工作。

比如應該先停止對檔案系統有讀寫操作的服務,然後再

umount

檔案系統。否則資料就會丟失。

這種順序的控制這也是依靠

/etc/rc。d/rcX。d/

目錄下所有指令碼的命名規則來控制的,在該目錄下所有以

K

開頭的指令碼都將在關閉系統時呼叫,字母

K

之後的數字定義了它們的執行順序。

這些指令碼負責安全地停止服務或者其他的關閉工作。

2。4 sysvinit 管理控制

此外,在系統啟動之後,管理員還需要對已經啟動的程序進行管理和控制。原始的

sysvinit

軟體包包含了一系列的控制啟動,執行和關閉所有其他程式的工具。

halt

停止系統

init

這個就是

sysvinit

本身的

init

程序實體,以

pid1

身份執行,是所有使用者程序的父程序,最主要的作用是在啟動過程中使用

/etc/inittab

檔案建立程序

killall5

就是

SystemV

killall

命令,向除自己的會話(session)程序之外的其它程序發出訊號,所以不能殺死當前使用的

shell

last

回溯

/var/log/wtmp

檔案(或者

-f

選項指定的檔案),顯示自從這個檔案建立以來,所有使用者的登入情況

lastb

作用和

last

差不多,預設情況下使用

/var/log/btmp

檔案,顯示所有失敗登入企圖

mesg

控制其它使用者對使用者終端的訪問

pidof

找出程式的程序識別號(

pid

),輸出到標準輸出裝置

poweroff

等於

shutdown -h –p

,或者

telinit 0

,關閉系統並切斷電源

reboot

等於

shutdown –r

或者

telinit 6

,重啟系統

runlevel

讀取系統的登入記錄檔案(一般是

/var/run/utmp

)把以前和當前的系統執行級輸出到標準輸出裝置

shutdown

以一種安全的方式終止系統,所有正在登入的使用者都會收到系統將要終止通知,並且不準新的登入

sulogin

當系統進入單使用者模式時,被

init

呼叫,當接收到啟動載入程式傳遞的

-b

選項時,

init

也會呼叫

sulogin

telinit

實際是

init

的一個連線,用來向

init

傳送單字元引數和訊號

utmpdump

以一種使用者友好的格式向標準輸出裝置顯示

/var/run/utmp

檔案的內容

wall

向所有有資訊許可權的登入使用者傳送訊息

不同的 Linux 發行版在這些

sysvinit

的基本工具基礎上又開發了一些輔助工具用來簡化

init

系統的管理工作。比如 RedHat 的 RHEL 在 sysvinit 的基礎上開發了

initscripts

軟體包,包含了大量的啟動指令碼 (如

rc。sysinit

) ,還提供了

service

chkconfig

等命令列工具,甚至一套圖形化介面來管理 init 系統。其他的 Linux 發行版也有各自的

initscript

或其他名字的

init

軟體包來簡化

sysvinit

的管理。

只要您理解了

sysvinit

的機制,在一個最簡的僅有

sysvinit

的系統下,您也可以直接呼叫指令碼啟動和停止服務,手動建立

inittab

和建立軟連線來完成這些任務。因此理解

sysvinit

的基本原理和命令是最重要的。您甚至也可以開發自己的一套管理工具。

2。5 sysvinit 小結

sysvinit 的優點是概念簡單

Service

開發人員只需要編寫啟動和停止指令碼,

概念非常清楚

service

新增/刪除到某個

runlevel

時,只需要執行一些建立/刪除軟連線檔案的

基本操作

這些都

不需要

學習額外的知識或特殊的定義語法(

UpStart

Systemd

都需要使用者學習新的定義系統初始化行為的語言)

sysvinit

的另一個重要優點是

確定的執行順序

指令碼嚴格按照啟動數字的大小順序執行,一個執行完畢再執行下一個,這非常有益於錯誤排查

UpStart

systemd

支援併發啟動,導致沒有人可以確定地瞭解具體的啟動順序,排錯不易

但是序列地執行指令碼導致

sysvinit

執行效率較慢,在新的

IT

環境下,啟動快慢成為一個重要問題

此外動態裝置載入等

Linux

新特性也暴露出

sysvinit

設計的一些問題

針對這些問題,人們開始想辦法改進

sysvinit

,以便加快啟動時間,並解決

sysvinit

自身的設計問題

3。 UpStart 的特點和使用

假如您使用的 Linux 發行版是 Ubuntu,很可能會發現在您的計算機上找不到/etc/inittab 檔案了,這是因為 Ubuntu 使用了一種被稱為 upstart 的新型 init 系統。

3。1 Upstart 簡介

開發Upstart的緣由

2.6 核心

支援下,一旦新外設連線到系統,核心便可以自動實時地發現它們,並初始化這些裝置,進而使用它們。這為行動式裝置使用者提供了很大的靈活性。

可是這些特性為

sysvinit

帶來了一些挑戰。當系統初始化時,需要被初始化的裝置並沒有連線到系統上;比如印表機。為了管理列印任務,系統需要啟動

CUPS

等服務,而如果印表機沒有接入系統的情況下,啟動這些服務就是一種浪費。

Sysvinit

沒有辦法處理這類需求,它必須一次性把所有可能用到的服務都啟動起來,即使印表機並沒有連線到系統,

CUPS

服務也必須啟動。

還有網路共享盤的掛載問題。在

/etc/fstab

中,可以指定系統自動掛載一個網路盤,比如

NFS

,或者

iSCSI

裝置。在本文的第一部分

sysvinit

的簡介中可以看到,

sysvinit

分析

/etc/fstab

掛載檔案系統這個步驟是在網路啟動之前。可是如果網路沒有啟動,

NFS

或者

iSCSI

都不可訪問,當然也無法進行掛載操作。

Sysvinit

採用

netdev

的方式來解決這個問題,即

/etc/fstab

發現

netdev

屬性掛載點的時候,不嘗試掛載它,在網路初始化並使能之後,還有一個專門的

netfs

服務來掛載所有這些網路盤。這是一個不得已的補救方法,給管理員帶來不便。部分新手管理員甚至從來也沒有聽說過

netdev

選項,因此經常成為系統管理的一個陷阱。

針對以上種種情況,

Ubuntu

開發人員在評估了當時的幾個可選

init

系統之後,決定重新設計和開發一個全新的

init

系統,即

UpStart

UpStart

基於事件機制,比如

U 盤

插入

USB

介面後,

udev

得到核心通知,發現該裝置,這就是一個新的事件。

UpStart

在感知到該事件之後觸發相應的等待任務,比如處理

/etc/fstab

中存在的掛載點。採用這種

事件驅動的模式

upstart

完美地解決了即插即用裝置帶來的新問題。

此外,採用事件驅動機制也帶來了一些其它有益的變化,比如加快了系統啟動時間。

sysvinit

執行時是同步阻塞的。一個指令碼執行的時候,後續指令碼必須等待。這意味著所有的初始化步驟都是序列執行的,而實際上很多服務彼此並不相關,完全可以並行啟動,從而減小系統的啟動時間。在

Linux

大量應用於伺服器的時代,系統啟動時間也許還不那麼重要;然而對於桌面系統和行動式裝置,啟動時間的長短對使用者體驗影響很大。此外雲計算等新的

Server

端技術也往往需要單個裝置可以更加快速地啟動。

使用Upstart 的特點

UpStart

解決了之前提到的 sysvinit 的缺點。採用

事件驅動模型

,UpStart 可以:

更快地啟動系統

當新硬體被發現時動態啟動服務

硬體被拔除時動態停止服務

3。2 Upstart 概念和術語

Upstart

的基本概念和設計清晰明確。UpStart 主要的概念是

job

和 **

event

**。

Job

就是一個工作單元,用來完成一件工作,比如啟動一個後臺服務,或者執行一個配置命令。

每個

Job

都等待一個或多個

事件

,一旦事件發生,

upstart

就觸發該

job

完成相應的工作。

3。2。1 Job 介紹

Job

就是一個工作的單元,一個任務或者一個服務。可以理解為

sysvinit

中的一個服務指令碼

有三種類型的工作

task job

task job

代表在一定時間內會執行完畢的任務,比如刪除一個檔案

service job

service job

代表後臺服務程序,比如

apache httpd

這裡程序一般不會退出,一旦開始執行就成為一個後臺精靈程序,由

init

程序管理,如果這類程序退出,由

init

程序重新啟動,它們只能由

init

程序傳送訊號停止它們的停止一般也是由於所依賴的停止事件而觸發的,不過

upstart

也提供命令列工具,讓管理人員手動停止某個服務

abstract job

abstract job

僅由

upstart

內部使用,僅對理解 upstart 內部機理有所幫助。我們不用關心它。除了以上的分類之外,還有另一種工作(Job)分類方法。Upstart 不僅可以用來為整個系統的初始化服務,也可以為每個使用者會話(session)的初始化服務。系統的初始化任務就叫做

system job

,比如掛載檔案系統的任務就是一個 system job;使用者會話的初始化服務就叫做

session job

3。2。2 Job 生命週期

Upstart

為每個工作都維護一個生命週期。一般來說,工作有開始,執行和結束這幾種狀態。為了更精細地描述工作的變化,Upstart 還引入了一些其它的狀態。

比如開始就有開始之前(

pre-start

),即將開始(

starting

)和已經開始了(

started

)幾種不同的狀態,這樣可以更加精確地描述工作的當前狀態。

工作從某種初始狀態開始,逐漸變化,或許要經歷其它幾種不同的狀態,最終進入另外一種狀態,形成一個狀態機。在這個過程中,當工作的狀態即將發生變化的時候,

init

程序會發出相應的事件(

event

)。

Linux初始化init系統

Linux初始化init系統

Linux初始化init系統

Linux初始化init系統

其中有四個狀態會引起

init

程序傳送相應的事件,表明該工作的相應變化:

Starting

Started

Stopping

Stopped

3。2。3 事件 Event

顧名思義,

Event

就是一個事件。事件在 upstart 中以通知訊息的形式具體存在。一旦某個事件發生了,

Upstart

就向整個系統傳送一個訊息。沒有任何手段阻止事件訊息被 upstart 的其它部分知曉,也就是說,事件一旦發生,整個

upstart

系統中所有工作和其它的事件都會得到通知。

Event 可以分為三類: signal,methods 或者 hooks

Signals

Signal

事件是非阻塞的,非同步的,傳送一個訊號之後控制權立即返回

Methods

Methods

事件是阻塞的,同步的

Hooks

Hooks

事件是阻塞的,同步的,它介於 Signals 和 Methods 之間,呼叫發出 Hooks 事件的程序必須等待事件完成才可以得到控制權,但不檢查事件是否成功

事件是個非常抽象的概念

下面我羅列出一些常見的事件,希望可以幫助您進一步瞭解事件的含義:

系統上電啟動,init 程序會發送”start”事件

根檔案系統可寫時,相應 job 會發送檔案系統就緒的事件

一個塊裝置被發現並初始化完成,傳送相應的事件

某個檔案系統被掛載,傳送相應的事件

類似 atd 和 cron,可以在某個時間點,或者週期的時間點發送事件

另外一個 job 開始或結束時,傳送相應的事件

一個磁碟檔案被修改時,可以發出相應的事件

一個網路裝置被發現時,可以發出相應的事件

預設路由被新增或刪除時,可以發出相應的事件

3。2。4 Job 和 Event 的相互協作

Upstart

就是由事件觸發工作執行的一個系統,每一個程式的執行都由其依賴的事件發生而觸發的。

系統初始化的過程是在工作和事件的相互協作下完成的

,可以大致描述如下:

系統初始化時,init 程序開始執行,init 程序自身會發出不同的事件,這些最初的事件會觸發一些工作執行。

每個工作執行過程中會釋放不同的事件,這些事件又將觸發新的工作執行。

如此反覆,直到整個系統正常執行起來。

工作配置檔案

任何一個工作都是由一個工作配置檔案(

Job Configuration File

)定義的。這個檔案是一個文字檔案,包含一個或者多個小節(

stanza

)。每個小節是一個完整的定義模組,定義了工作的一個方面,比如 author 小節定義了工作的作者。工作配置檔案存放在

/etc/init

下面,是以

。conf

作為檔案字尾的檔案。

# 一個最簡單的工作配置檔案#This is a simple demo of Job Configure file#This line is comment, start with ##Stanza 1, The authorauthor “Liu Ming”#Stanza 2, Descriptiondescription “This job only has author and description, so no use, just a demo”

上面的例子不會產生任何作用,一個真正的工作配置檔案會包含很多小節,其中比較重要的小節有以下幾個。

expect Stanza

Upstart 除了負責系統的啟動過程之外,和 SysVinit 一樣,Upstart 還提供一系列的管理工具。當系統啟動之後,管理員可能還需要進行維護和調整,比如啟動或者停止某項系統服務。或者將系統切換到其它的工作狀態,比如改變執行級別。本文後續將詳細介紹

Upstart 的管理工具

的使用。

為了啟動,停止,重啟和查詢某個系統服務。Upstart 需要跟蹤該服務所對應的程序。比如

httpd

服務的程序 PID 為 1000。當用戶需要查詢 httpd 服務是否正常執行時,Upstart 就可以利用 ps 命令查詢程序 1000,假如它還在正常執行,則表明服務正常。當用戶需要停止 httpd 服務時,Upstart 就使用

kill

命令終止該程序。為此,**

Upstart

必須跟蹤服務程序的程序號**。

部分服務程序為了將自己變成

後臺精靈程序

daemon

),會採用兩次派生(

fork

)的技術,另外一些服務則不會這樣做。假如一個服務派生了兩次,那麼 UpStart 必須採用第二個派生出來的程序號作為服務的 PID。但是,UpStart 本身無法判斷服務程序是否會派生兩次,為此在定義該服務的工作配置檔案中必須寫明

expect

小節,告訴 UpStart 程序是否會派生兩次。

Expect

有兩種,

expect fork

表示程序只會

fork 一次

expect daemonize

表示程序會

fork 兩次

exec Stanza 和 script Stanza

一個 UpStart 工作一定需要做些什麼,可能是執行一條 shell 命令,或者執行一段指令碼。用”

exec

“關鍵字配置工作需要執行的命令;用”

script

“關鍵字定義需要執行的指令碼。

# 顯示了 exec 和 script 的用法# script 例子# mountall。confdescription “Mount filesystems on boot”start on startupstop on starting rcS。。。script 。 /etc/default/rcS [ -f /forcefsck ] && force_fsck=”——force-fsck” [ “$FSCKFIX”=”yes” ] && fsck_fix=”——fsck-fix” 。。。 exec mountall –daemon $force_fsck $fsck_fixend script。。。

這是

mountall

的例子,該工作在系統啟動時執行,負責掛載所有的檔案系統。該工作需要執行復雜的指令碼,由”

script

“關鍵字定義;在指令碼中,使用了

exec

來執行

mountall

命令。

`start on Stanza 和 stop on Stanza

start on

“定義了觸發工作的所有事件。”start on”的語法很簡單,如下所示:

start on EVENT [[KEY=]VALUE]。。。 [and|or。。。]

EVENT

表示事件的名字,可以在 start on 中指定多個事件,表示該工作的開始需要依賴多個事件發生。多個事件之間可以用 and 或者 or 組合,”表示全部都必須發生”或者”其中之一發生即可”等不同的依賴條件。除了事件發生之外,工作的啟動還可以依賴特定的條件,因此在 start on 的 EVENT 之後,可以用 KEY=VALUE 來表示額外的條件,一般是某個環境變數(KEY)和特定值(VALUE)進行比較。如果只有一個變數,或者變數的順序已知,則 KEY 可以省略。

“stop on”和”start on”非常類似,只不過是定義工作在什麼情況下需要停止。

# start on/ stop on 例子#dbus。confdescription “D-Bus system message bus”start on local-filesystemsstop on deconfiguring-networking……

D-Bus

是一個系統訊息服務,上面的配置檔案表明當系統發出

local-filesystems

事件時啟動 D-Bus;當系統發出

deconfiguring-networking

事件時,停止 D-Bus 服務。

Session Init

UpStart

還可以用於管理使用者會話的初始化。在我寫這篇文章的今天,多數 Linux 發行版還沒有使用 UpStart 管理會話。只有在

Ubuntu Raring

版本中,使用 UpStart 管理使用者會話的初始化過程。

首先讓我們瞭解一下

Session

的概念。

Session

就是一個使用者會話,即使用者從遠端或者本地登入系統開始工作,直到使用者退出。這整個過程就構成一個會話。

每個使用者的使用習慣和使用方法都不相同,因此使用者往往需要為自己的會話做一個定製,比如新增特定的命令別名,啟動特殊的應用程式或者服務,等等。這些工作都屬於對特定會話的初始化操作,因此可以被稱為

Session Init

使用者使用

Linux

可以有兩種模式:

字元模式

圖形介面

。在字元模式下,會話初始化相對簡單。使用者登入後只能啟動一個

Shell

,透過 shell 命令使用系統。各種 shell 程式都支援一個自動執行的啟動指令碼,比如

~/。bashrc

。使用者在這些指令碼中加入需要執行的定製化命令。字元會話需求簡單,因此這種現有的機制工作的很好。

在圖形介面下,事情就變得複雜一些。使用者登入後看到的並不是一個 shell 提示符,而是一個桌面。一個完整的桌面環境由很多元件組成。

一個桌面環境包括

window manager

panel

以及其它一些定義在

/usr/share/gnome-session/sessions/

下面的基本元件;此外還有一些輔助的應用程式,共同幫助構成一個完整的方便的桌面,比如

system monitors

panel applets

NetworkManager

Bluetooth

printers

等。當用戶登入之後,這些元件都需要被初始化,這個過程比字元介面要複雜的多。目前啟動各種圖形元件和應用的工作由

gnome-session

完成。

過程如下

以 Ubuntu 為例,當用戶登入 Ubuntu 圖形介面後,顯示管理器(Display Manager)

lightDM

啟動

Xsession

。Xsession 接著啟動

gnome-session

,gnome-session 負責其它的初始化工作,然後就開始了一個

desktop session

# 傳統 desktop session 啟動過程init |- lightdm | |- Xorg | |- lightdm ——-session-child | |- gnome-session ——session=ubuntu | |- compiz | |- gwibber | |- nautilus | |- nm-applet | : | : | |- dbus-daemon ——session | : :

這個過程有一些缺點(和

sysVInit

類似)。一些應用和元件其實並不需要在會話初始化過程中啟動,更好的選擇是在需要它們的時候才啟動。比如

update-notifier

服務,該服務不停地監測幾個檔案系統路徑,一旦這些路徑上發現可以更新的軟體包,就提醒使用者。這些檔案系統路徑包括新插入的

DVD

盤等。

Update-notifier

gnome-session

啟動並一直執行著,在多數情況下,使用者並不會插入新的

DVD

,此時

update-notifier

服務一直在後臺執行並消耗系統資源。更好的模式是當用戶插入 DVD 的時候再執行

update-notifier

這樣可以加快啟動時間,減小系統執行過程中的記憶體等系統資源的開銷。對於移動,嵌入式等裝置等這還意味著省電。除了

Update-notifier

服務之外,還有其它一些類似的服務。比如

Network Manager

,一天之內使用者很少切換網路裝置,所以大部分時間

Network Manager

服務僅僅是在浪費系統資源;再比如

backup manager

等其它常駐記憶體,後臺不間斷執行卻很少真正被使用的服務。

UpStart

的基於事件的按需啟動的模式就可以很好地解決這些問題,比如使用者插入網線的時候才啟動

Network Manager

,因為使用者插入網線表明需要使用網路,這可以被稱為按需啟動。

下圖描述了採用

UpStart

之後的會話初始化過程。

# 採用 Upstart 的 Desktop session init 過程init |- lightdm | |- Xorg | |- lightdm ——-session-child | |- session-init # <—— upstart running as normal user | |- dbus-daemon ——session | |- gnome-session ——session=ubuntu | |- compiz | |- gwibber | |- nautilus | |- nm-applet | : | : : :

3。3 UpStart 使用

本文僅列出了少數工作配置檔案的語法。要全面掌握工作配置檔案的寫法,需要詳細閱讀

Upstart

手冊

。這裡讓我們來分析一下如何用

Upstart

來實現傳統的執行級別,進而瞭解如何靈活使用工作配置檔案。

3。3。1 系統執行級別

Upstart 的運作完全是基於工作和事件的。工作的狀態變化和執行會引起事件,進而觸發其它工作和事件。

而傳統的 Linux 系統初始化是基於執行級別的,即 SysVInit。因為歷史的原因,Linux 上的多數軟體還是採用傳統的 SysVInit 指令碼啟動方式,並沒有為 UpStart 開發新的啟動指令碼,因此即便在 Debian 和 Ubuntu 系統上,還是必須模擬老的 SysVInit 的執行級別模式,以便和多數現有軟體相容。

雖然 Upstart 本身並沒有執行級別的概念,但完全可以用 UpStart 的工作模擬出來。讓我們完整地考察一下 UpStart 機制下的系統啟動過程。

3。3。2 系統啟動過程

下圖描述了 UpStart 的啟動過程

Linux初始化init系統

Linux初始化init系統

系統上電後執行

GRUB

載入核心。核心執行硬體初始化和核心自身初始化。在核心初始化的最後,核心將啟動

pid

1

init

程序,即

UpStart

程序。

Upstart

程序在執行了一些自身的初始化工作後,立即發出”

startup

“事件。上圖中用紅色方框加紅色箭頭表示事件,可以在左上方看到”

startup

“事件。

所有依賴於”

startup

“事件的工作被觸發,其中最重要的是

mountall

mountall

任務負責掛載系統中需要使用的檔案系統,完成相應工作後,

mountall

任務會發出以下事件:

local-filesystem

virtual-filesystem

all-swaps

其中

virtual-filesystem

事件觸發

udev

任務開始工作。任務

udev

觸發

upstart-udev-bridge

的工作。

Upstart-udev-bridge

會發出

net-device-up IFACE=lo

事件,表示本地迴環

IP

網路已經準備就緒。同時,任務

mountall

繼續執行,最終會發出

filesystem

事件。

此時,任務 rc-sysinit 會被觸發,因為 rc-sysinit 的 start on 條件如下:

start on filesystem and net-device-up IFACE=lo

任務

rc-sysinit

呼叫

telinit

Telinit

任務會發出

runlevel

事件,觸發執行

/etc/init/rc。conf

rc。conf

執行

/etc/rc$。d/

目錄下的所有指令碼,和

SysVInit

非常類似。

3。3。3 開發注意事項

作為程式開發人員,在編寫系統服務時,需要了解 UpStart 的一些特殊要求。只有符合這些要求的軟體才可以被 UpStart 管理。

規則一,派生次數需宣告

很多 Linux 後臺服務都透過派生兩次的技巧將自己變成後臺服務程式。如果您編寫的服務也採用了這個技術,就必須透過文件或其它的某種方式明確地讓

UpStart

的維護人員知道這一點,這將影響 UpStart 的

expect stanza

,我們在前面已經詳細介紹過這個

stanza

的含義

規則二,派生後即可用

後臺程式在完成第二次派生的時候,必須保證服務已經可用。因為

UpStart

透過派生計數來決定服務是否處於就緒狀態

規則三,遵守 SIGHUP 的要求

UpStart

會給精靈程序傳送

SIGHUP

訊號,此時,

UpStart

希望該精靈程序做以下這些響應工作:

完成所有必要的重新初始化工作,比如重新讀取配置檔案。這是因為

UpStart

的命令”

initctl reload

“被設計為可以讓服務在不重啟的情況下更新配置。

精靈程序必須繼續使用現有的

PID

,即收到

SIGHUP

時不能呼叫

fork

。如果服務必須在這裡呼叫

fork

,則等同於派生兩次,參考上面的規則一的處理。這個規則保證了

UpStart

可以繼續使用

PID

管理本服務

規則四,收到 SIGTEM 即 shutdown

當收到

SIGTERM

訊號後,

UpStart

希望精靈程序程序立即乾淨地退出,釋放所有資源。如果一個程序在收到

SIGTERM

訊號後不退出,Upstart 將對其傳送

SIGKILL

訊號。

3。3。4 Upstart 命令

作為系統管理員,一個重要的職責就是管理系統服務。比如系統服務的監控,啟動,停止和配置。UpStart 提供了一系列的命令來完成這些工作。其中的核心是**

initctl

**,這是一個帶子命令風格的命令列工具。

# 可以用 initctl list 來檢視所有工作的概況:# initctl listalsa-mixer-save stop/waitingavahi-daemon start/running, process 690mountall-net stop/waitingrc stop/waitingrsyslog start/running, process 482screen-cleanup stop/waitingtty4 start/running, process 859udev start/running, process 334upstart-udev-bridge start/running, process 304ureadahead-other stop/waiting

這是在

Ubuntu10。10

系統上的輸出,其它的 Linux 發行版上的輸出會有所不同。第一列是工作名,比如

rsyslog

。第二列是工作的目標;第三列是工作的狀態。

initctl stop

停止一個正在執行的工作

initctl start

開始一個工作

initctl status

來檢視一個工作的狀態

initctl restart

重啟一個工作

initctl reload

可以讓一個正在執行的服務重新載入配置檔案

這些命令和傳統的

service

命令十分相似

Linux初始化init系統

Linux初始化init系統

文章作者:

Escape

文章連結:

https://www。escapelife。site/posts/4fb48da7。html

相關文章

頂部