整個流程的起點是IServiceManager::defaultServiceManager()
可以看到這是壹個單例,在首次調用的時候會進行初始化獲取servicemanager的binder,然後用智能指針封裝壹下。
可以看到這兒還是壹個單例,對於參與binder IPC的進程,和binder驅動交互部分就是通過ProcessState實現的。
對於android,有三種binder驅動節點,下面列壹下區別:
接下來看下ProcessState的構造方法:
這兒有兩個和驅動交互的部分,壹個是open_driver,壹個是mmap,這裏先介紹下open_driver:
這兒的流程比較直接,就是打開節點,用ioctl獲取了版本號,設置了線程池數量,設置了允許異步調用檢測。接下來看下open 的內容,這時候就會進入內核,因為binder驅動定義了自己的open,ioctl,mmap方法。
接下來看下init_binder_device的實現:
這兒就是將binder驅動設備註冊為壹個misc設備,並指定了它的操作實現方法。
因為上層是先調用的open,因此看下這兒binder_open的實現:
這兒主要就是創建了壹個binder_proc結構,並和當前用戶態進程current關聯起來。
再看下ioctl的內容:
看到這壹塊,之前的三個ioctl命令內容就清楚了。接下來需要看下壹個關鍵的地方,就是mmap,對應的實現就是binder_mmap:
這兒沒做啥,看下binder_alloc_mmap_handler:
這時候驅動做的事情就是將用戶態的地址保存到proc自己的結構裏面。 mmap暫時告壹段落。
繼續回到用戶態,繼續ProcessState::self()->getContextObject(nullptr) 獲取serviemanager的binder過程,前壹部分介紹完了,接下來應該是getContextObject部分,看下實現:
對於servicemanager,handle為0,看下getStrongProxyForHandle的內容:
如果本地沒有servicemanager的proxy binder,那麽就需要用驅動獲取。繼續看下獲取流程:
看下transact:
可以看到transact裏面的流程就是封裝數據包和與驅動交互,如果有返回值,則直接寫入reply。先看下如何封裝的數據包:
這時候就把請求相關的寫入了parcel,接下來看下waitForResponse:
看下talkWithDriver:
這兒就是將請求寫入binder_write_read,並和驅動進行交互。在進入驅動前,先看下binder_write_read的結構:
在驅動中,ioctl的操作如下:
先看下binder_get_thread的操作:
binder_get_thread_ilocked的邏輯如下:
拿到線程後,接下來就是binder_ioctl_write_read:
這兒就是讀取內容,然後解析出命令,對於我們,命令是BC_TRANSACTION, 然後調用binder_transaction進行操作:
到這裏,過去servicemanager的binder流程就結束了。最後再簡單看下binder_proc_transaction的內容:
介紹到這裏,defaultServiceManager涉及的流程就介紹完了,最後用壹個流程圖總結下:
本篇介紹了下servicemanager proxy的獲取流程,涉及了ProcessState(進程單例), IPCThreadState(線程單例)。 binder驅動的open,mmap,ioctl部分。該流程比起其他調用流程稍微簡單壹些,不過對於熟悉binder 工作流程還是很有幫助的。