天天看點

Ubuntu init啟動流程分析

      現行的linux distros主流的有兩種init方式:一種是廣為流傳的system v initialization,它來源于unix并且至今仍被各種linux distros所采用;另一種是近幾年提出的upstart方式,基于事件機制,系統的所有服務,任務都是由事件驅動的。據我所知,采用後一種方式的目前有ubuntu(6.10 and later),fedora(9.10

and later),debian(optional)。雖然采用upstart的發行版并不多,但它旨在取代舊式的system v initialization。

  作為知識梳理,我現在就先在這裡總結一下這兩種方式各自的初始化流程,這也是為了友善整理思路:

  之前在查找linux系統init流程的相關資料時總是能夠看到inittab的身影,但是在我的ubuntu上是沒有這個檔案的,到後來才知道采用 upstart方式的ubuntu上是沒有inittab這個檔案的。在舊式的system v initialization中,/etc/inittab可是個相當重要的檔案。init程序啟動後第一時間找的就是它!inittab負責初始化系統,設定系統runlevel及進 入各runlevel對應要執行的指令。假設目前inittab中設定的預設runlevle是5,則init會運作/etc/init.d/rc

5指令,該指令會依據系統服務的依賴關系周遊執行/etc/rc5.d中的腳本/程式。進入/etc/rc5.d目錄可以發現裡面的檔案都是到/etc /init.d/下對應的腳本/程式的軟連結。以s開頭的為啟動的意思,以k開頭的為停止。并且s/k後面的兩位數數字代表了服務的啟動順序(由服務依賴關系決定)。

  那麼upstart job是怎麼樣的呢?我們知道,system v initializaiton是以runlevel為核心,依據服務間依賴關系的init方式,但在upstart job,runlevel雖說對于服務的啟動也有影響但已不是關鍵所在。upstart job是事件驅動的,系統服務的啟動、停止等等均是由事件決定的,反過來,系統服務的啟動、停止也可以作為事件源觸發其他服務。并且事件并不一定得由系統内部産生,使用者可以手工的鍵入start/stop

[service]産生事件來啟動/終止服務。man upstart-evnets檢視upstart job所定義的事件,可以發現,runlevel也被當作事件來對待(因runlevel的改變而産生的事件),諸如此類還有其他如 startup,started,filesystem等等。那麼系統服務又是如何知道自己應該什麼時候啟動,什麼時候終止的呢?答案就在于/etc /init中(有的distros可能是在/etc/event.d)。進入/etc/init目錄下一看,均是系統服務的配置檔案,或者說,是job

definition files。(實際上upstart init隻需要/etc/init這麼一個目錄,不像system v init,“拐彎抹腳”轉好多圈才到達目的地,在性能上不如前者)。随便打開一個檔案,比如cron.conf:

  相信敏銳的程式猿們都發現了:start on runlevel [2345];stop on runlevel [!2345]

  沒錯,配置檔案就是通過這個來設定服務何時啟動,何時終止的。

  實際上并不僅僅在系統啟動初期,在系統運轉的任何時期都可以通過發送事件來啟動或終止服務。這便是upstart job的優點之一,除了用于系統初始化,還可以在系統運作階段發揮作用。相比之下system v initialization方式下的配置檔案一般隻用于系統初始化階段,當然系統運作階段我們可以通過/etc/init.d/service start/stop/othercommand來操作服務,但很明顯不如upstart方式簡潔明白。

  好,介紹完system v initialization和upstart,那麼現在就能介紹ubuntu init系統初始化流程。前面提過ubuntu使用的是upstart方式的initialization,其實不全然,考慮到6.10之前的版本采用的system v init及某些服務的需要,ubuntu采用的是相容模式,即:系統中既有system v-style啟動的服務,也有upstart啟動的服務。如果你使用的是ubuntu11.04(我目前pc上的系統),那麼你可以看到系統中有這麼幾個目錄:

  作為兩種init方式各自特征的/etc/init.d,/etc/rc${runlevel}.d目錄和/etc/init目錄在ubuntu中都有了,那麼ubuntu是如何實作相容的?實際上,ubuntu中并沒有直接采用system v-style啟動服務,要知道,ubuntu中的init已被替換為upstart init,而system v-style的服務是存放于/etc/rc${runlevel}.d目錄中的,(而/etc/rc${runlevle}.d/下的檔案是到/etc/init.d的軟連結)可upstart

init并不會直接跑到這裡面去啟動服務。它是通過間接調用來啟動這類服務的。換句話說,ubuntu中的init并不會直接奔着/etc/init.d或者/etc/rc${runlevel}.d/而去,它采用了折衷的辦法,通過/etc/init下的某些配置檔案調用/etc/rc${runlevel}.d/中的腳本以啟動采用舊式system v-style的服務。唉,說的我自己都覺得好繞,還是見執行個體吧,看下面。

  進入/etc/init目錄(upstart init會到該目錄下讀取配置檔案),會發現幾個跟rc有關的配置檔案:

  rc-sysinit在startup事件發生時被啟動,rc在系統runlevel變化時被啟動,rcs在系統runlevel為s時啟動。在配置檔案的注釋中說明了,這幾個檔案,正是upstart init處理system v-style服務的關鍵。

  rc-sysinit在startup事件發生時被啟動,即,upstart init會首先讀取rc-sysinit.conf并執行相關配置和腳本。rc-sysinit.conf的主要工作是設定系統預設runlevel,檢測是否存在/etc/inittab或核心指令行,若存在,則按核心指令行>/etc/inittab>預設runlevel的順序設定系統 runlevel。最後,調用telinit進入設定的runlevel。

  由于調用了telinit進入了設定的runlevel,runlevel改變的事件發生,此時rc服務啟動(當然其他服務也會)。那麼,我們就有必要來看看rc.conf中到底有什麼東西。打開rc.conf,注意到最後一行:

  是不是感覺/etc/init.d/rc很熟悉,沒錯,在system v initialization中,/etc/inittab中的各runlevel對應的指令行就是通過這種形式設定的。

  很明顯,/etc/init.d/rc被調用了,并且傳入了早前設定好的系統runlevel作為參數。而/etc/init.d/rc會根據傳入 的runlevel參數調用/etc/rc${runlevel}.d/下的腳本(以s開頭)以啟動服務,終止在前次runlevel啟動而目前在 runlevel需要終止的服務。至此,ubuntu處理system v-style服務的流程是不是漸漸明朗了。通過rc-sysinit和rc間接的調用/etc/init.d/rc進而啟動system

v-style服務,ubuntu在采用新式upstart init照顧了舊式的system v init。

  采用upstart方式啟動的服務則在/etc/init/目錄中有屬于自己的一份配置檔案,終端下鍵入:initctl list,看看列出的服務是否同/etc/init/下的服務完全一緻!

  over!!!

  另:上面的内容很多是我個人的了解,大方向應該沒錯,但細節處的了解就不敢保證拉。看官發現了别忘了給出建議喲!

  btw,rc這東西代表的是run commands不?看了wiki好似是這樣子的:it is used for any file that contains startup information for a command。曾經有段時間分不清是run commands還是runtime configuration~_~!

<a target="_blank" href="http://www.cnblogs.com/cassvin/archive/2011/12/25/ubuntu_init_analysis.html">轉載位址</a>

繼續閱讀