淺析Linux初始化init系統,第3部分: Systemd

Systemd 的簡介和特色

Systemd 是 Linux 系統中最新的初始化系統(init),它主要的設計目標是克服 sysvinit 固有的缺點,提升系統的啓動速度。systemd 和 ubuntu 的 upstart 是競爭對手,預計會取代 UpStart,實際上在做者寫做本文時,已經有消息稱 Ubuntu 也將採用 systemd 做爲其標準的系統初始化系統。html

Systemd 的不少概念來源於蘋果 Mac OS 操做系統上的 launchd,不過 launchd 專用於蘋果系統,所以長期未能得到應有的普遍關注。Systemd 借鑑了不少 launchd 的思想,它的重要特性以下:linux

同 SysVinit 和 LSB init scripts 兼容

Systemd 是一個"新來的",Linux 上的不少應用程序並無來得及爲它作相應的改變。和 UpStart 同樣,systemd 引入了新的配置方式,對應用程序的開發也有一些新的要求。若是 systemd 想替代目前正在運行的初始化系統,就必須和現有程序兼容。任何一個 Linux 發行版都很難爲了採用 systemd 而在短期內將全部的服務代碼都修改一遍。ubuntu

Systemd 提供了和 Sysvinit 以及 LSB initscripts 兼容的特性。系統中已經存在的服務和進程無需修改。這下降了系統向 systemd 遷移的成本,使得 systemd 替換現有初始化系統成爲可能。安全

更快的啓動速度

Systemd 提供了比 UpStart 更激進的並行啓動能力,採用了 socket / D-Bus activation 等技術啓動服務。一個顯而易見的結果就是:更快的啓動速度。服務器

爲了減小系統啓動時間,systemd 的目標是:網絡

  • 儘量啓動更少的進程併發

  • 儘量將更多進程並行啓動socket

一樣地,UpStart 也試圖實現這兩個目標。UpStart 採用事件驅動機制,服務能夠暫不啓動,當須要的時候才經過事件觸發其啓動,這符合第一個設計目標;此外,不相干的服務能夠並行啓動,這也實現了第二個目標。ide

下面的圖形演示了 UpStart 相對於 SysVInit 在併發啓動這個方面的改進:高併發

圖 1. UpStart 對 SysVinit 的改進

UpStart 對 SysVinit 的改進

假設有 7 個不一樣的啓動項目, 好比 JobA、Job B 等等。在 SysVInit 中,每個啓動項目都由一個獨立的腳本負責,它們由 sysVinit 順序地,串行地調用。所以總的啓動時間爲 T1+T2+T3+T4+T5+T6+T7。其中一些任務有依賴關係,好比 A,B,C,D。

而 Job E 和 F 卻和 A,B,C,D 無關。這種狀況下,UpStart 可以併發地運行任務{E,F,(A,B,C,D)},使得總的啓動時間減小爲 T1+T2+T3。

這無疑增長了系統啓動的並行性,從而提升了系統啓動速度。可是在 UpStart 中,有依賴關係的服務仍是必須前後啓動。好比任務 A,B,(C,D)由於存在依賴關係,因此在這個局部,仍是串行執行。

讓咱們例舉一些例子, Avahi 服務須要 D-Bus 提供的功能,所以 Avahi 的啓動依賴於 D-Bus,UpStart 中,Avahi 必須等到 D-Bus 啓動就緒以後纔開始啓動。相似的,livirtd 和 X11 都須要 HAL 服務先啓動,而全部這些服務都須要 syslog 服務記錄日誌,所以它們都必須等待 syslog 服務先啓動起來。然而 httpd 和他們都沒有關係,所以 httpd 能夠和 Avahi 等服務併發啓動。

Systemd 可以更進一步提升併發性,即使對於那些 UpStart 認爲存在相互依賴而必須串行的服務,好比 Avahi 和 D-Bus 也能夠併發啓動。從而實現以下圖所示的併發啓動過程:

圖 2. systemd 的併發啓動

systemd 的併發啓動

全部的任務都同時併發執行,總的啓動時間被進一步下降爲 T1。

可見 systemd 比 UpStart 更進一步提升了並行啓動能力,極大地加速了系統啓動時間。

systemd 提供按需啓動能力

當 sysvinit 系統初始化的時候,它會將全部可能用到的後臺服務進程所有啓動運行。而且系統必須等待全部的服務都啓動就緒以後,才容許用戶登陸。這種作法有兩個缺點:首先是啓動時間過長;其次是系統資源浪費。

某些服務極可能在很長一段時間內,甚至整個服務器運行期間都沒有被使用過。好比 CUPS,打印服務在多數服務器上不多被真正使用到。您可能沒有想到,在不少服務器上 SSHD 也是不多被真正訪問到的。花費在啓動這些服務上的時間是沒必要要的;一樣,花費在這些服務上的系統資源也是一種浪費。

Systemd 能夠提供按需啓動的能力,只有在某個服務被真正請求的時候才啓動它。當該服務結束,systemd 能夠關閉它,等待下次須要時再次啓動它。

Systemd 採用 Linux 的 Cgroup 特性跟蹤和管理進程的生命週期

init 系統的一個重要職責就是負責跟蹤和管理服務進程的生命週期。它不只能夠啓動一個服務,也必須也可以中止服務。這看上去沒有什麼特別的,然而在真正用代碼實現的時候,您或許會發現中止服務比一開始想的要困難。

服務進程通常都會做爲精靈進程(daemon)在後臺運行,爲此服務程序有時候會派生(fork)兩次。在 UpStart 中,須要在配置文件中正確地配置 expect 小節。這樣 UpStart 經過對 fork 系統調用進行計數,從而獲知真正的精靈進程的 PID 號。好比圖 3 所示的例子:

圖 3. 找到正確 pid

找到正確 pid

若是 UpStart 找錯了,將 p1`做爲服務進程的 Pid,那麼中止服務的時候,UpStart 會試圖殺死 p1`進程,而真正的 p1``進程則繼續執行。換句話說該服務就失去控制了。

還有更加特殊的狀況。好比,一個 CGI 程序會派生兩次,從而脫離了和 Apache 的父子關係。當 Apache 進程被中止後,該 CGI 程序還在繼續運行。而咱們但願服務中止後,全部由它所啓動的相關進程也被中止。

爲了處理這類問題,UpStart 經過 strace 來跟蹤 fork、exit 等系統調用,可是這種方法很笨拙,且缺少可擴展性。systemd 則利用了 Linux 內核的特性即 CGroup 來完成跟蹤的任務。當中止服務時,經過查詢 CGroup,systemd 能夠確保找到全部的相關進程,從而乾淨地中止服務。

CGroup 已經出現了好久,它主要用來實現系統資源配額管理。CGroup 提供了相似文件系統的接口,使用方便。當進程建立子進程時,子進程會繼承父進程的 CGroup。所以不管服務如何啓動新的子進程,全部的這些相關進程都會屬於同一個 CGroup,systemd 只須要簡單地遍歷指定的 CGroup 便可正確地找到全部的相關進程,將它們一一中止便可。

啓動掛載點和自動掛載的管理

傳統的 Linux 系統中,用戶能夠用/etc/fstab 文件來維護固定的文件系統掛載點。這些掛載點在系統啓動過程當中被自動掛載,一旦啓動過程結束,這些掛載點就會確保存在。這些掛載點都是對系統運行相當重要的文件系統,好比 HOME 目錄。和 sysvinit 同樣,Systemd 管理這些掛載點,以便可以在系統啓動時自動掛載它們。Systemd 還兼容/etc/fstab 文件,您能夠繼續使用該文件管理掛載點。

有時候用戶還須要動態掛載點,好比打算訪問 DVD 內容時,才臨時執行掛載以便訪問其中的內容,而不訪問光盤時該掛載點被取消(umount),以便節約資源。傳統地,人們依賴 autofs 服務來實現這種功能。

Systemd 內建了自動掛載服務,無需另外安裝 autofs 服務,能夠直接使用 systemd 提供的自動掛載管理能力來實現 autofs 的功能。

實現事務性依賴關係管理

系統啓動過程是由不少的獨立工做共同組成的,這些工做之間可能存在依賴關係,好比掛載一個 NFS 文件系統必須依賴網絡可以正常工做。Systemd 雖然可以最大限度地併發執行不少有依賴關係的工做,可是相似"掛載 NFS"和"啓動網絡"這樣的工做仍是存在天生的前後依賴關係,沒法併發執行。對於這些任務,systemd 維護一個"事務一致性"的概念,保證全部相關的服務均可以正常啓動而不會出現互相依賴,以致於死鎖的狀況。

可以對系統進行快照和恢復

systemd 支持按需啓動,所以系統的運行狀態是動態變化的,人們沒法準確地知道系統當前運行了哪些服務。Systemd 快照提供了一種將當前系統運行狀態保存並恢復的能力。

好比系統當前正運行服務 A 和 B,能夠用 systemd 命令行對當前系統運行情況建立快照。而後將進程 A 中止,或者作其餘的任意的對系統的改變,好比啓動新的進程 C。在這些改變以後,運行 systemd 的快照恢復命令,就可當即將系統恢復到快照時刻的狀態,即只有服務 A,B 在運行。一個可能的應用場景是調試:好比服務器出現一些異常,爲了調試用戶將當前狀態保存爲快照,而後能夠進行任意的操做,好比中止服務等等。等調試結束,恢復快照便可。

這個快照功能目前在 systemd 中並不完善,彷佛開發人員也沒有特別關注它,所以有報告指出它還存在一些使用上的問題,使用時尚需慎重。

日誌服務

systemd 自帶日誌服務 journald,該日誌服務的設計初衷是克服現有的 syslog 服務的缺點。好比:

  • syslog 不安全,消息的內容沒法驗證。每個本地進程均可以聲稱本身是 Apache PID 4711,而 syslog 也就相信並保存到磁盤上。

  • 數據沒有嚴格的格式,很是隨意。自動化的日誌分析器須要分析人類語言字符串來識別消息。一方面此類分析困難低效;此外日誌格式的變化會致使分析代碼須要更新甚至重寫。

Systemd Journal 用二進制格式保存全部日誌信息,用戶使用 journalctl 命令來查看日誌信息。無需本身編寫複雜脆弱的字符串分析處理程序。

Systemd Journal 的優勢以下:

  • 簡單性:代碼少,依賴少,抽象開銷最小。

  • 零維護:日誌是除錯和監控系統的核心功能,所以它本身不能再產生問題。舉例說,自動管理磁盤空間,避免因爲日誌的不斷產生而將磁盤空間耗盡。

  • 移植性:日誌 文件應該在全部類型的 Linux 系統上可用,不管它使用的何種 CPU 或者字節序。

  • 性能:添加和瀏覽 日誌 很是快。

  • 最小資源佔用:日誌 數據文件須要較小。

  • 統一化:各類不一樣的日誌存儲技術應該統一塊兒來,將全部的可記錄事件保存在同一個數據存儲中。因此日誌內容的全局上下文都會被保存而且可供往後查詢。例如一條固件記錄後一般會跟隨一條內核記錄,最終還會有一條用戶態記錄。重要的是當保存到硬盤上時這三者之間的關係不會丟失。Syslog 將不一樣的信息保存到不一樣的文件中,分析的時候很難肯定哪些條目是相關的。

  • 擴展性:日誌的適用範圍很廣,從嵌入式設備到超級計算機集羣均可以知足需求。

  • 安全性:日誌 文件是能夠驗證的,讓沒法檢測的修改再也不可能。

轉載於:http://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html

相關文章
相關標籤/搜索