ServiceManager在init程序啟動之後啟動,用來管理系統中的service,那麼首先了解一下在init程序啟動之後啟動這句話類:
一般開機過程分為三個階段:
1. OS級别,由bootloader載入linux核心後,核心開始初始化,并載入built-in的驅動程式,核心完成開機後,載入init process,切換至user-space後,結束核心的循序過程,進入排成模式。
2. Android-level,由init process開始,讀取init.rc,Mative服務啟動,并啟動重要的外部程式,例如servicemanager、zygote以及system service。
3. Zygote-Mode,Zygote啟動完System Service後,進入Zygote Mode,在Socket等候指令,随後,使用者将看到一個桌面環境,桌面環境由一個名為Launcher的應用程式負責提供。
image.png
在ServiceManager中有兩個比較重要的方法:add_service和check_service,系統的service需要通過add_service把自己的資訊注冊到servicemanager中,當需要使用時,通過check_service檢查該service是否存在。看它的main函數的源碼:
image.png
三件事:
1. 打開Binder裝置,并在記憶體中映射128k的空間
首先看一下struct binder_state這個結構體
struct binder_state{
int fd; //檔案描述符,打開/dev/binder裝置
void* mapped; //把裝置檔案/dev/binder映射到程序空間的起始位址
unsigned mapsize; //映射記憶體空間的大小
}
2. 告訴Binder驅動程式,自己是Binder上下文管理者
3.進入循環,不停去讀Binder裝置,看是否有對service的請求,如果有的話就去調用svcmgr_handller函數回調處理請求。
下面就來看一下servicemanager是怎麼循環等待用戶端的請求,并進行注冊服務、服務擷取這一系列活動的。
等待用戶端請求
ServiceManager程序通過binder_loop方法進入循環等待用戶端的請求中,當有用戶端請求時,程序ServiceManager被喚醒并調用svcmgr_handler來處理用戶端的請求。
image.png
1. ServiceManager程序在進入循環前,調用binder_write()方法,通過ioctl系統調用設定Binder線程的運作狀态為BINDER_LOOPER_STATE_ENTERED,看下binder_write()方法的源碼:
image.png
首先設定binder_write_read結構體變量的值,然後通過ioctl傳遞到Binder驅動程式中,此時控制指令為BINDER_WRITE_READ,binder_ioctl函數中對BINDER_WRITE_READ指令的處理過程為:
image.png
在binder_thread_write方法中,對BC_ENTER_LOOPER Binder協定的處理如下:
image.png
此處僅僅設定了binder_thread結構體變量中的線程運作狀态looper為BINDER_LOOPER_STATE_ENTERED,表示目前的binder線程進入循環狀态。
2. 睡眠等待用戶端請求
在沒有用戶端請求時,目前程序就進入休眠狀态,等待請求到來再喚醒。
總結一哈?
ServiceManager程序的啟動首先打開binder驅動并開辟核心緩存區,同時将緩存區的實體頁面同時映射到核心虛拟位址空間及程序虛拟位址空間中,然後在核心中建立屬于servicemanager程序的binder_node實體節點,接着設定處理用戶端請求的binder線程運作狀态,由于此時沒有用戶端的請求,servicemanager程序進入睡眠等待中,直到用戶端請求的到來時,喚醒servicemanager程序,再繼續往下執行。
服務注冊
直接來看,當有service請求時,調用的回到函數svcmgr_handler函數。
image.png
image.png
如果請求注冊,就執行紅色框中的代碼,我們再來看一下具體實作do_add_service()方法是怎麼實作的:
image.png
image.png
看代碼中的三個紅框,首先會檢查是否有權限注冊service,如果沒有權限就直接傳回不能注冊;然後去檢查該service是否已經注冊過了,如果已經注冊過,那就不能再注冊;再判斷記憶體是否夠用。如果都沒有問題,就會注冊該service,加入到svcList中來,(在servicemanager中維護service資訊的地方就是svcList,裡面存了service的name和handler)。通過以上幾步,service就算注冊成功了。
服務擷取
如果是服務擷取,就會執行代碼中的黃色框,并将傳回的資料寫入reply,傳回給用戶端,do_find_service函數中主要執行service的查找,看源碼:
image.png
其他:
android 程序間通信---Service Manager(1)
作者:哎呦呦胖子斌
連結:https://www.jianshu.com/p/601a2e9721dd
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。