Binder系列4—獲取ServiceManager

基于Android 6.0的源碼剖析焕毫, 本文詳細地講解defaultServiceManager流程


一. 概述

獲取Service Manager是通過defaultServiceManager()方法來完成堕战,當進程注冊服務(addService)或獲取服務(getService)的過程之前狡汉,都需要先調(diào)用defaultServiceManager()方法來獲取gDefaultServiceManager對象患民。對于gDefaultServiceManager對象懈凹,如果存在則直接返回泪蔫;如果不存在則創(chuàng)建該對象蹦狂,創(chuàng)建過程包括調(diào)用open()打開binder驅(qū)動設備磨总,利用mmap()映射內(nèi)核的地址空間嗦明。

1.1 流程圖


1.2 defaultServiceManager

[-> IServiceManager.cpp]


獲取ServiceManager對象采用單例模式,當gDefaultServiceManager存在蚪燕,則直接返回娶牌,否則創(chuàng)建一個新對象。 發(fā)現(xiàn)與一般的單例模式不太一樣馆纳,里面多了一層while循環(huán)诗良,這是google在2013年1月Todd Poynor提交的修改。當嘗試創(chuàng)建或獲取ServiceManager時鲁驶,ServiceManager可能尚未準備就緒鉴裹,這時通過sleep 1秒后,循環(huán)嘗試獲取直到成功灵嫌。gDefaultServiceManager的創(chuàng)建過程,可分解為以下3個步驟:

ProcessState::self():用于獲取ProcessState對象(也是單例模式)壹罚,每個進程有且只有一個ProcessState對象,存在則直接返回寿羞,不存在則創(chuàng)建猖凛,詳情見【小節(jié)二】;

getContextObject(): 用于獲取BpBinder對象,對于handle=0的BpBinder對象绪穆,存在則直接返回辨泳,不存在才創(chuàng)建,詳情見【小節(jié)三】;

interface_cast():用于獲取BpServiceManager對象玖院,詳情見【小節(jié)四】;

二. 獲取ProcessState對象

2.1 ProcessState::self

[-> ProcessState.cpp]


獲得ProcessState對象: 這也是單例模式菠红,從而保證每一個進程只有一個ProcessState對象。其中gProcess和gProcessMutex是保存在Static.cpp類的全局變量难菌。

2.2 初始化ProcessState

[-> ProcessState.cpp]


ProcessState的單例模式的惟一性试溯,因此一個進程只打開binder設備一次,其中ProcessState的成員變量mDriverFD記錄binder驅(qū)動的fd,用于訪問binder設備郊酒。

BINDER_VM_SIZE = (1*1024*1024) - (4096 *2), binder分配的默認內(nèi)存大小為1M-8k遇绞。

DEFAULT_MAX_BINDER_THREADS = 15,binder默認的最大可并發(fā)訪問的線程數(shù)為16燎窘。

2.3 open_driver

[-> ProcessState.cpp]


open_driver作用是打開/dev/binder設備摹闽,設定binder支持的最大線程數(shù)。關于binder驅(qū)動的相應方法褐健,見文章Binder Driver初探付鹿。

三. 獲取BpBinder對象

3.1 getContextObject

[-> ProcessState.cpp]


獲取handle=0的IBinder

3.2 getStrongProxyForHandle

[-> ProcessState.cpp]


當handle值所對應的IBinder不存在或弱引用無效時會創(chuàng)建BpBinder,否則直接獲取。 針對handle==0的特殊情況舵匾,通過PING_TRANSACTION來判斷是否準備就緒俊抵。如果在context manager還未生效前,一個BpBinder的本地引用就已經(jīng)被創(chuàng)建纽匙,那么驅(qū)動將無法提供context manager的引用务蝠。

3.3 lookupHandleLocked

[-> ProcessState.cpp]


根據(jù)handle值來查找對應的handle_entry,handle_entry是一個結構體拍谐,里面記錄IBinder和weakref_type兩個指針烛缔。當handle大于mHandleToObject的Vector長度時,則向該Vector中添加(handle+1-N)個handle_entry結構體轩拨,然后再返回handle向?qū)恢玫膆andle_entry結構體指針践瓷。

3.4 創(chuàng)建BpBinder

[-> BpBinder.cpp]


創(chuàng)建BpBinder對象中會將handle相對應Binder的弱引用增加1.

四. 獲取BpServiceManager

4.1 interface_cast

[-> IInterface.h]


這是一個模板函數(shù),可得出亡蓉,interface_cast()?等價于?IServiceManager::asInterface()晕翠。接下來,再來說說asInterface()函數(shù)的具體功能。

4.2 IServiceManager::asInterface

對于asInterface()函數(shù)砍濒,通過搜索代碼淋肾,你會發(fā)現(xiàn)根本找不到這個方法是在哪里定義這個函數(shù)的, 其實是通過模板函數(shù)來定義的,通過下面兩個代碼完成的:


接下來爸邢,再說說這兩行代碼分別完成的功能:

4.3 DECLARE_META_INTERFACE

[-> IInterface.h]


位于IServiceManager.h文件中,INTERFACE=ServiceManager展開即可得:

[-> IServiceManager.h]


該過程主要是聲明asInterface(),getInterfaceDescriptor()方法.

4.4 IMPLEMENT_META_INTERFACE

[-> IInterface.h]


位于IServiceManager.cpp文件中,INTERFACE=ServiceManager, NAME=”android.os.IServiceManager”展開即可得:

[-> IServiceManager.cpp]

不難發(fā)現(xiàn)樊卓,[小節(jié)4.2]的IServiceManager::asInterface()?等價于?new BpServiceManager()。在這里杠河,更確切地說應該是new BpServiceManager(BpBinder)碌尔。

4.5 BpServiceManager實例化

創(chuàng)建BpServiceManager對象的過程,會先初始化父類對象:

4.5.1 BpServiceManager初始化

[-> IServiceManager.cpp]


4.5.2 BpInterface初始化

[-> IInterface.h]


4.5.3 BpRefBase初始化

[-> Binder.cpp]


new BpServiceManager()券敌,在初始化過程中唾戚,比較重要工作的是類BpRefBase的mRemote指向new BpBinder(0),從而BpServiceManager能夠利用Binder進行通過通信待诅。

五. 總結

defaultServiceManager 等價于 new BpServiceManager(new BpBinder(0));

ProcessState::self()主要工作:

調(diào)用open()叹坦,打開/dev/binder驅(qū)動設備;

再利用mmap()卑雁,創(chuàng)建大小為1M-8K的內(nèi)存地址空間募书;

設定當前進程最大的最大并發(fā)Binder線程個數(shù)為16。

BpServiceManager巧妙將通信層與業(yè)務層邏輯合為一體序厉,

通過繼承接口IServiceManager實現(xiàn)了接口中的業(yè)務邏輯函數(shù)锐膜;

通過成員變量mRemote= new BpBinder(0)進行Binder通信工作。

BpBinder通過handler來指向所對應BBinder, 在整個Binder系統(tǒng)中handle=0代表ServiceManager所對應的BBinder弛房。

5.1 模板函數(shù)

Native層的Binder架構,通過如下兩個宏,非常方便地創(chuàng)建了new Bp##INTERFACE(obj):


例如:


等價于:

.....

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末道盏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荷逞,老刑警劉巖媒咳,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異种远,居然都是意外死亡涩澡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門坠敷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妙同,“玉大人,你說我怎么就攤上這事膝迎≈嘀悖” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵限次,是天一觀的道長芒涡。 經(jīng)常有香客問我,道長卖漫,這世上最難降的妖魔是什么费尽? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮羊始,結果婚禮上旱幼,老公的妹妹穿的比我還像新娘。我一直安慰自己店枣,他們只是感情好速警,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鸯两,像睡著了一般闷旧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钧唐,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天忙灼,我揣著相機與錄音,去河邊找鬼钝侠。 笑死该园,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的帅韧。 我是一名探鬼主播里初,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼忽舟!你這毒婦竟也來了双妨?” 一聲冷哼從身側響起淮阐,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎刁品,沒想到半個月后泣特,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡挑随,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年状您,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兜挨。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡膏孟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出暑劝,到底是詐尸還是另有隱情骆莹,我是刑警寧澤颗搂,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布担猛,位于F島的核電站,受9級特大地震影響丢氢,放射性物質(zhì)發(fā)生泄漏傅联。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一疚察、第九天 我趴在偏房一處隱蔽的房頂上張望蒸走。 院中可真熱鬧,春花似錦貌嫡、人聲如沸比驻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽别惦。三九已至,卻和暖如春夫椭,著一層夾襖步出監(jiān)牢的瞬間掸掸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工蹭秋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扰付,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓仁讨,卻偏偏與公主長得像羽莺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子洞豁,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容