ServiceManager在init行程啟動之后啟動,用來管理系統中的service,那么首先理解一下在init行程啟動之后啟動這句話類:
一般開機程序分為三個階段:
- OS級別,由bootloader載入linux內核后,內核開始初始化,并載入built-in的驅動程式,內核完成開機后,載入init process,切換至user-space后,結束內核的循序程序,進入排成模式,
- Android-level,由init process開始,讀取init.rc,Mative服務啟動,并啟動重要的外部程式,例如servicemanager、zygote以及system service,
- Zygote-Mode,Zygote啟動完System Service后,進入Zygote Mode,在Socket等候命令,隨后,使用者將看到一個桌面環境,桌面環境由一個名為Launcher的應用程式負責提供,

在ServiceManager中有兩個比較重要的方法:add_service和check_service,系統的service需要通過add_service把自己的資訊注冊到servicemanager中,當需要使用時,通過check_service檢查該service是否存在,看它的main函式的原始碼:

三件事:
- 打開Binder設備,并在記憶體中映射128k的空間
首先看一下struct binder_state這個結構體
struct binder_state{
int fd; //檔案描述符,打開/dev/binder設備
void* mapped; //把設備檔案/dev/binder映射到行程空間的起始地址
unsigned mapsize; //映射記憶體空間的大小
}
-
告訴Binder驅動程式,自己是Binder背景關系管理者
-
進入回圈,不停去讀Binder設備,看是否有對service的請求,如果有的話就去呼叫svcmgr_handller函式回呼處理請求,
下面就來看一下servicemanager是怎么回圈等待客戶端的請求,并進行注冊服務、服務獲取這一系列活動的,
等待客戶端請求
ServiceManager行程通過binder_loop方法進入回圈等待客戶端的請求中,當有客戶端請求時,行程ServiceManager被喚醒并呼叫svcmgr_handler來處理客戶端的請求,

- ServiceManager行程在進入回圈前,呼叫binder_write()方法,通過ioctl系統呼叫設定Binder執行緒的運行狀態為BINDER_LOOPER_STATE_ENTERED,看下binder_write()方法的原始碼:

首先設定binder_write_read結構體變數的值,然后通過ioctl傳遞到Binder驅動程式中,此時控制命令為BINDER_WRITE_READ,binder_ioctl函式中對BINDER_WRITE_READ命令的處理程序為:

在binder_thread_write方法中,對BC_ENTER_LOOPER Binder協議的處理如下:

此處僅僅設定了binder_thread結構體變數中的執行緒運行狀態looper為BINDER_LOOPER_STATE_ENTERED,表示當前的binder執行緒進入回圈狀態,
2. 睡眠等待客戶端請求
在沒有客戶端請求時,當前行程就進入休眠狀態,等待請求到來再喚醒,
總結一哈?
ServiceManager行程的啟動首先打開binder驅動并開辟內核快取區,同時將快取區的物理頁面同時映射到內核虛擬地址空間及行程虛擬地址空間中,然后在內核中創建屬于servicemanager行程的binder_node物體節點,接著設定處理客戶端請求的binder執行緒運行狀態,由于此時沒有客戶端的請求,servicemanager行程進入睡眠等待中,直到客戶端請求的到來時,喚醒servicemanager行程,再繼續往下執行,
服務注冊
直接來看,當有service請求時,呼叫的回到函式svcmgr_handler函式,

如果請求注冊,就執行紅色框中的代碼,我們再來看一下具體實作do_add_service()方法是怎么實作的:


看代碼中的三個紅框,首先會檢查是否有權限注冊service,如果沒有權限就直接回傳不能注冊;然后去檢查該service是否已經注冊過了,如果已經注冊過,那就不能再注冊;再判斷記憶體是否夠用,如果都沒有問題,就會注冊該service,加入到svcList中來,(在servicemanager中維護service資訊的地方就是svcList,里面存了service的name和handler),通過以上幾步,service就算注冊成功了,
服務獲取
如果是服務獲取,就會執行代碼中的黃色框,并將回傳的資料寫入reply,回傳給客戶端,do_find_service函式中主要執行service的查找,看原始碼:

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/34280.html
標籤:Android
