歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 淺析 Linux 初始化 init 系統,第 3 部分: Systemd

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

日期:2017/2/28 14:25:09   编辑:Linux教程

近年來,Linux 系統的 init 進程經歷了兩次重大的演進,傳統的 sysvinit 已經逐漸淡出歷史舞台,新的 UpStart 和 systemd 各有特點,越來越多的 Linux 發行版采納了 systemd。本文簡要介紹了這三種 init 系統的使用和原理,每個 Linux 系統管理員和系統軟件開發者都應該了解它們,以便更好地管理系統和開發應用。本文是系列的第 3 部分,主要講述 systemd 的特點和使用。

Systemd 的簡介和特點

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

Systemd 的很多概念來源於蘋果 Mac OS 操作系統上的 launchd,不過 launchd 專用於蘋果系統,因此長期未能獲得應有的廣泛關注。Systemd 借鑒了很多 launchd 的思想,它的重要特性如下:

同 SysVinit 和 LSB init scripts 兼容

Systemd 是一個"新來的",Linux 上的很多應用程序並沒有來得及為它做相應的改變。和 UpStart 一樣,systemd 引入了新的配置方式,對應用程序的開發也有一些新的要求。如果 systemd 想替代目前正在運行的初始化系統,就必須和現有程序兼容。任何一個 Linux 發行版都很難為了采用 systemd 而在短時間內將所有的服務代碼都修改一遍。

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

更快的啟動速度

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

為了減少系統啟動時間,systemd 的目標是:

  • 盡可能啟動更少的進程
  • 盡可能將更多進程並行啟動

同樣地,UpStart 也試圖實現這兩個目標。UpStart 采用事件驅動機制,服務可以暫不啟動,當需要的時候才通過事件觸發其啟動,這符合第一個設計目標;此外,不相干的服務可以並行啟動,這也實現了第二個目標。

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

圖 1. 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 的並發啟動

所有的任務都同時並發執行,總的啟動時間被進一步降低為 T1。

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

Linux 引導方式systemd upstart sysV http://www.linuxidc.com/Linux/2014-01/95555.htm

為什麼systemd會被如此迅速的采用? http://www.linuxidc.com/Linux/2014-08/105789.htm

systemd 與 sysVinit 彩版對照表 http://www.linuxidc.com/Linux/2014-09/106455.htm

Linux Systemd——在RHEL/CentOS 7中啟動/停止/重啟服務 http://www.linuxidc.com/Linux/2014-08/105975.htm

太有用了!用systemd命令來管理Linux系統! http://www.linuxidc.com/Linux/2014-09/106490.htm

systemd 提供按需啟動能力

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

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

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

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

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

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

圖 3. 找到正確 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.linuxidc.com/Linux/2014-12/110383p2.htm

Copyright © Linux教程網 All Rights Reserved