一、啓動總流程圖
kernel和initrd: 探測硬件->加載驅動(initrd, 微型linux)->掛載根文件系統->rootfs(/sbin/init) 。initrd不是必須的。
二、三個主要的init
講述三個主要的 Init 系統:sysvinit,UpStart 和 systemd
1、sysvinit
SysVinit 順序運行(串行),概念簡單清晰、啓動慢。啓動流程如下:
init--->inittab(runlevel)--->rc.sysinit(系統初始化)--->rc--->rcX.d(啓停服務)--->rc.local--->tty和login
缺點:頻繁地使用硬件熱插拔技術,sysvinit需要默認就啓動所有可能使用的硬件對應的服務;網絡共享盤的掛載(nfs、iSCSI),需要netfs 服務來掛載所有這些網絡盤;啓動慢。
2、upstart
Upstart 採用事件驅動模型。更快地啓動系統(並行);當新硬件被發現時動態啓動服務;硬件被拔除時動態停止服務。
UpStart 主要的概念是 job 和 event。Job 就是一個工作單元,用來完成一件工作,比如啓動一個後臺服務,或者運行一個配置命令。每個 Job 都等待一個或多個事件,一旦事件發生,upstart 就觸發該 job 完成相應的工作。
開機upstart首先產生startup事件。
3、systemd
systemd 的最大特點有兩個:
(1)、提供了比 UpStart 更激進的並行啓動能力,採用了 socket / D-Bus activation 等技術啓動服務。結果就是:更快的啓動速度。
(2)、用 CGroup 統計跟蹤子進程,乾淨可靠。
3.1、並行化Socket
對於傳統的 Unix daemon,彼此的真正依賴是服務所提供的 socket。
如果能儘早建立客戶程序所必須的 socket 而令客戶程序處於等待狀態而不是在服務程序完全啓動後再啓動客戶程序,我們就能加快啓動進程,進一步並行化進程啓動。
3.2、並行化Bus服務
Linux上現代的daemon都通過DBus而非socket來交互。
DBus已經提供了所有必要的hook:使用DBus將會在第一次訪問時加載服務,並且給予最小的、每請求一個的、消費 者與生產者同時啓動的同步機制。
例如Avahi與CUPS(CUPS需要Avahi進行 mDNS/DNS-SD上打印機掃描)同時啓動,僅僅是簡單的同時啓動二者,若CUPS比Avahi啓動快,則DBus將把請求緩存入隊列,直到 Avahi服務進行了處理。
總結如下:基於Socket和基於DBus的服務可一次並行啓動所有進程,無需任何額外的同步。基於激活的策略還能令我們進行延遲加載服務。 如果服務很少被用到,我們可以在第一次被訪問時啓動,而不是在啓動過程中啓動。
3.3、並行化文件系統任務
系統啓動過程中,文件系統相關的活動是最耗時的,比如掛載文件系統,fsck,磁盤配額檢查等。
Systemd 集成了 autofs 的實現,對於系統中的掛載點,比如/home,當系統啓動的時候,systemd 爲其創建一個臨時的自動掛載點。在這個時刻/home 真正的掛載設備尚未啓動好,真正的掛載操作還沒有執行,文件系統檢測也還沒有完成。可是那些依賴該目錄的進程已經可以併發啓動,他們的 open()操作被內建在 systemd 中的 autofs 捕獲,將該 open()調用掛起(可中斷睡眠狀態)。然後等待真正的掛載操作完成,文件系統檢測也完成後,systemd 將該自動掛載點替換爲真正的掛載點,並讓
open()調用返回。由此,實現了那些依賴於文件系統的服務和文件系統本身同時併發啓動。
3.3.1、三個init啓動時間示意圖
3.3.2、systemd設置運行級別:
systemd執行的第一個目標是default.target
獲取當前的運行級別:systemctl get-default
設置:systemctl set-default multi-user.target
/lib/systemd/system/default.target -> graphical.target
3.3.3、systemd與sysvinit運行級別對應表