Android init進程

本文爲讀書筆記,如有侵權,請聯繫我 
    linux中的所有進程都是由Init進程創建並運行的。首先linux內核啓動,然後在用戶空間中,啓動init進程,再依次啓動系統運行所需的其他進程。在系統啓動完成後,init進程會作爲守護進程監視其他進程。若某個監視中的進程一旦終結,進入將僵死狀態,它就會釋放進程所佔用的系統資源。在android平臺也有init進程。出上述功能外,還有其他功能。
下面分幾部分應該掌握的:
一。 啓動,首先啓動linux,內核,然後進入用戶空間,啓動init進程,再依次啓動系統運行所需的其他進程。
再系統啓動完成後,init進程會作爲守護進程監視其他進程。
二。 init進程主要提供4大功能
 init不僅進行(1)子進程的終止服務,(2)當應用程序訪問設備驅動時,還會生成設備節點文件,(3)同時提供屬性服務,保存系統運行所需的環境變量。還會(4)分析init.rc啓動腳本文件,根據相關文文件中的內容,執行相應的功能。下面是詳細說明:
   init進程是android系統啓動後,由內核啓動的第一個用戶級進程,其啓動過程如下:源碼分析如下:
   首先init註冊SIGCHLD信號處理器,用於處理子進程產生的信號(linux進程間相互發送消息來實現進程間的通信,這些消息就是信號,而對子進程產生的信號,再init的事件處理循環中進行)。
   init註冊玩信號處理器後,然後創建並掛載啓動所需的目錄。像/dev, /pro, /sys等的系統運行時目錄,再系統終止時,會消失。生成運行時目錄後,創建運行日誌輸出設備
   在生成輸出設備後,開始解析init.rc文件。 init.rc是init啓動後的執行腳本,記錄着init進程執行的功能,此文件定義在system/core/rootdir/目錄下,包括init.rc和init.{hardware}.rc文件,用於環境設置與通用的進程相關的定義。 此過程中,會根據init.rc中的定義生成服務列表和動作列表,分別以鏈表的形式掛載再service_list與action_list上
   接着創建init進程中已經定義好的節點文件(device_init())
   然後開始初始化屬性服務(property_init())
   接下來系統加載開機logo
           執行與動作列表的init區相關的命令。
   啓動屬性服務(start_property_service())
   接着創建套接字,以便init進程再收到子進程終止的信息SIGCHLD信號時,調用相應的handler
           程序開始執行與Action list的early-boot, boot ,  property相關的命令
   設置事件處理循環的監聽事件。

下面對init源碼分析,並對其提供的4個功能分別說明:
(1)init.rc腳本文件的分析與執行
         解析此腳本,設置系統環境,記錄待處理的進程。生成service_list與action_list相關的列表。動作列表用來創建目錄,以及爲某些特定文件指定權限。服務列表用來記錄初始化程序需要啓動的一些程序。
   動作列表與服務列表通過drain_action_queue()函數來運行
(2)創建設備節點文件
   android應用程序通過設備驅動訪問硬件,設備節點文件是設備驅動的邏輯文件,應用程序使用設備節點文件來訪問設備驅動程序。要創建設備節點,需要遵循android提供的創建設備節點的方法:靜態和動態
靜態創建
  Linux中,運行所需的設備節點文件是預先定義再/dev目錄下,應用程序無需經過其他步驟,通過事先定義好的設備節點文件即可訪問設備驅動。再android系統的根文件系統不存再/dev目錄,因此係統運行中,需要一個進程來創建設備節點文件,而此進程就是init進程。
  init進程通過兩種方式創建設備節點文件,第一種,以預先定義好的設備信息爲基礎,當init進程啓動時,統一創建設備節點文件; 第二種,在系統運行中,當有設備插入usb端口時,init進程就會接收到這一事件,爲插入的設備動態創建設備節點文件。
  第一種方法是連接已定義的設備,稱爲冷拔插;而第二種方法是在系統運行的狀態下連接設備,稱爲熱拔插。

創建節點文件
  linux通過mknod使用程序創建設備節點文件。linux引入udev使用程序,udev以守護進程的形式運行,當設備驅動被加載時,它會掌握主設備號,次設備號,以及設備類型,而後再/dev下創建設備節點文件。
  下圖爲從加載驅動到udev創建設備節點文件的整個過程。再系統運行中,若某個設備被插入,內核就會加載與該設備相關的驅動程序,而後驅動調用驅動函數probe(),將主設備號,次設備號,以及設備類型保存到/sys文件系統中。然後發出uevent,並傳遞給udev守護進程。
  
 TIP: uevent 是內核向用戶空間進程傳遞信息的信號系統,即在添加或刪除設備時,內核使用uevent將設備信息傳遞到用戶空間。uevent包含設備名稱,類別,主設備號,次設備號,設備節點文件創建的目錄等信息,並將這些信息傳遞給udev守護進程。udev守護進程監聽uevent,當uevent發生時,它接受並讀取其中的設備信息,而後創建設備節點文件。
   udev以守護進程的形式運行,通過監聽分析內核發出的uevent,查看註冊在/sys目錄下的設備信息,而後在/dev目錄相應位置創建設備節點文件。系統內核啓動後,udev進程運行在用戶空間內,它無法處理內核啓動過程中發生的uevent。雖然內核空間內的設備驅動程序可以正常運行,但由於未創建訪問設備驅動所需的設備節點文件,將會出現應用程序無法使用相關設備的問題。
   linux系統中,在udev守護進程運行前,通過提供與加載的設備驅動程序冷拔插機制,來解決設備節點文件沒有被創建的問題。當插入設備時,熱拔插機制會立即進行處理,而冷拔插與熱拔插有着不同的處理機制。當內核啓動後,冷拔插機制啓動udev守護進程,從/sys目錄下讀取事先註冊好的設備信息,而後引發與各設備相對應的uevent,創建設備節點文件。android也採用這種處理方式來創建設備節點文件,不同的是使用init進程來扮演udev守護進程的角色。
   android的binder驅動程序即是採用熱插拔的方式創建設備節點的。Binder驅動是一個虛擬的設備,不存在物理硬件,被用在進程間的RPC。一個應用程序若想使用BInder,需要通過/dev/binder設備節點來訪問Binder驅動程序。
   當內核啓動時,BInder驅動程序在初始化函數misc_register()函數中,將創建設備節點文件所需的信息保存到/sys目錄下。由於Binder驅動程序應該由用戶級進程init創建設備節點文件,但由於系統處於內核啓動,無法發生uevent,因此僅僅向/sys目錄註冊驅動程序信息,而後創建設備節點文件。
   內核啓動完畢後,init進程啓動,對於像binder驅動程序這樣無法創建設備節點的驅動,將採用冷拔插方式進行處理,init進程事先獲知等待冷拔插處理的驅動程序,並事先定義好各驅動程序的設備節點文件(在android中,/system/core/init/device.c中列出了init進程創建的節點文件目錄)。然後調用mknod()創建設備節點文件。

動態創建
   熱插拔由init的事件處理循環來完成。

(3)進程的終止再啓動
   init進程讀取並分析init.rc文件,後的服務列表,而後從列表中依次啓動服務子進程。init啓動的主進程如下:
    sh 搭載android的機器終端,連接串口或adbd時,提供控制檯輸入輸出的shell程序
    adbd 調試服務
    servicemanager 用來管理系統中的服務。
    vold 用來掛載/管理USB存儲或SD卡設備
    playmp3 在android啓動時,輸出聲音。
   除了上述進程外,還啓動了其他多種進程。若init啓動某進程終止,會對系統運行產生影響,則init進程會重新啓動它們。

(4)屬性服務
   屬性變更請求是init事件處理循環處理的另一個事件。在android平臺中,爲了讓運行中的所有進程共享系統運行時所需要的各種設置值,系統開闢了屬性存儲區域,並提供了訪問該區域的api。在android平臺中,屬性服務得到了系統的應用,再訪問屬性值時,添加了訪問權限控制,增強了訪問的安全性。系統忠所有運行忠的進程都可以訪問屬性值,但僅由init進程才能修改屬性值。其他進程修改屬性值時,需要向init進程發送請求,最終由init進程負責修改屬性值。init進程會檢查各屬性訪問權限,而後修改。當屬性更改後,若定義在init.rc文件中的某個特定條件得到滿足,則與次條件相匹配的動作就會發生。每個動作都有一個觸發器(trigger),它決定動作的執行時間,記錄在on property 關鍵字後的命令就會被執行。
   下面是init進程與其他進程在訪問病修改屬性值的大致情形:

    屬性值被android存放在一塊共享內存中,作爲ashmem(android shared memory)。












































發佈了46 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章