本篇文章是《深入理解Android內(nèi)核設(shè)計(jì)思想》的讀書筆記,可能就沒書本來得詳細(xì)。

Binder分為四個(gè)部分
- Binder驅(qū)動(dòng):運(yùn)行于內(nèi)核態(tài),可以提供open(),ioctl(),mmap()等常用的文件操作
- ServiceManager:保存所有Binder Server。
- Binder Client
- Binder Service
一.Binder驅(qū)動(dòng)
- 打開Binder驅(qū)動(dòng)-binder-open,在里面創(chuàng)建了一個(gè)它自己的binder_proc實(shí)體
binder_proc是Binder驅(qū)動(dòng)為應(yīng)用進(jìn)程分配的一個(gè)數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)和該進(jìn)程有關(guān)的所有信息,如內(nèi)存分配線程管理等。
binder-open{
生成binder_proc對(duì)象
binder_proc初始化
把它添加到Binder的全局管理中(資源互斥添加)
}
到這里,Binder驅(qū)動(dòng)已經(jīng)為用戶創(chuàng)建了一個(gè)它自己的binder_proc實(shí)體,之后用戶對(duì)Binder的設(shè)備操作將以這個(gè)對(duì)象為基礎(chǔ)。
-
binder_mmap,最多支持4MB的操作
對(duì)于應(yīng)用程序而言,調(diào)用mmap()方法可以把設(shè)備指定的內(nèi)存塊映射到應(yīng)用程序的內(nèi)存空間中
而對(duì)于Binder驅(qū)動(dòng)來說,上層用戶調(diào)用的mmap()最終就對(duì)應(yīng)了binder_mmap()對(duì)于應(yīng)用程序,它通過mmap()返回值得到一個(gè)虛擬內(nèi)存地址,之后通過虛擬內(nèi)存轉(zhuǎn)換(分段分頁)最終指向物理地址某個(gè)地方
對(duì)于Binder驅(qū)動(dòng)而言,有個(gè)指針binder_proc->buffer指向某個(gè)虛擬內(nèi)存地址,與應(yīng)用程序指向一樣,兩者共用內(nèi)存
binder_ioctl
可以替代read,write。對(duì)應(yīng)命令 INDER_WRITE_READ,承擔(dān)Binder驅(qū)動(dòng)的大部分業(yè)務(wù)小結(jié)
Binder驅(qū)動(dòng)并沒有脫離Linux的典型驅(qū)動(dòng)模型,它提供了多個(gè)文件操作接口mmap,ioctl。其binder_ioctl實(shí)現(xiàn)了應(yīng)用程序與Binder驅(qū)動(dòng)之間的命令交互,可以說承載了Binder驅(qū)動(dòng)中的大部分業(yè)務(wù)。
二.ServiceManager - Binder Service
ServiceManager啟動(dòng)
在init.rc時(shí)啟動(dòng)(參考系統(tǒng)啟動(dòng)章節(jié)),如果它發(fā)生重啟,其他系統(tǒng)服務(wù)zygote,media,surfaceflinger,drm也會(huì)被重新加載ServiceManager構(gòu)建
int main{
binder_open打開Binder設(shè)備,做好初始化(各種內(nèi)存地址)
binder_become_context_manager將自己設(shè)為Binder大管家,整個(gè)Android程序中只允許一個(gè)ServiceManager存在
binder_loop進(jìn)入主循環(huán)
}
* binder_open初始化
> * binder_state 記錄SM中有關(guān)于Binder的所有信息
* mmap由Binder驅(qū)動(dòng)決定被映射到進(jìn)程空間中的內(nèi)存起始地址
* 映射區(qū)大小為128K,只讀
* 從文件的起始地址開始映射
* binder_become_context_manager初始化
> * 調(diào)用到ioctl方法
* ioctl方法中發(fā)送向Binder Driver發(fā)送 **BINDER_SET_CONTEXT_MGR**的ioctl命令使其成為大管家。(只要向Binder驅(qū)動(dòng)發(fā)送BINDER_SET_CONTEXT_MGR的ioctl命令即可,因?yàn)镾ervicerManager啟動(dòng)的很早,能確保它是系統(tǒng)中第一個(gè)向Binder驅(qū)動(dòng)注冊成管家的程序)
* binder_loop循環(huán)等待客戶端請(qǐng)求
> * binder_write_read 執(zhí)行**BINDER_WRITE_READ**所需的數(shù)據(jù)格式
* 開始循環(huán)讀取消息(它的消息是從Binder驅(qū)動(dòng)那里獲取的)
* 從Binder驅(qū)動(dòng)讀取消息,通過**BINDER_WRITE_READ**命令
* binder_parse處理消息
* 不斷循環(huán),而且永遠(yuǎn)不會(huì)主動(dòng)退出,除非出現(xiàn)致命錯(cuò)誤
ServiceManager的功能架構(gòu)比較簡潔,內(nèi)部維護(hù)著一個(gè)svclist列表,用于存儲(chǔ)所有Server(Binder Service)的相關(guān)信息(以svcinfo為數(shù)據(jù)結(jié)構(gòu)),查詢和注冊都是基于這個(gè)表展開
- 獲取ServiceManager服務(wù)
準(zhǔn)確說,獲取SM服務(wù)是Binder Client需要做的工作之一。
訪問SM服務(wù)流程
1.打開Binder設(shè)置
2.執(zhí)行mmap內(nèi)存映射
3.通過Binder驅(qū)動(dòng)向SM發(fā)送請(qǐng)求(SM的handle為0)
4.獲取結(jié)果
每個(gè)進(jìn)程只允許打開一次Binder設(shè)備,且只做一次內(nèi)存映射---所有需要使用Binder驅(qū)動(dòng)的線程共享這一資源。
獲取SM服務(wù)流程圖

進(jìn)程中ProcessState和IPCThreadState這兩個(gè)類專用與Binder驅(qū)動(dòng)通信,所以Java層代碼使用Binder驅(qū)動(dòng)實(shí)際上是基于他們來完成的,我們稱為BpBinder。
應(yīng)用程序通過代理ServiceManagerProxy(能夠跨進(jìn)程調(diào)用)來獲取到SM服務(wù),它所能提供的服務(wù)和服務(wù)端的SM必須是一致的,也就是它也要實(shí)現(xiàn)服務(wù)端SM對(duì)應(yīng)的接口。
這里的SM指的是Binder層面的ServiceManager。
對(duì)于獲取SM服務(wù)的代理ServiceManagerProxy,Android系統(tǒng)在ServiceManagerProxy上又加了一層封裝ServiceManager.java
2.1 獲取SM服務(wù)
首先調(diào)用ServiceManager.getService(name)
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
其中sCache用于記錄getService的歷史查詢結(jié)果,加快查詢速度。如果不在則調(diào)用getIServiceManager().getService(name);
getIServiceManager方法用于獲取一個(gè)IServiceManager對(duì)象,而IServiceManager接口的實(shí)現(xiàn)類則是ServiceManagerProxy
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
調(diào)用ServiceManagerNative的方法
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
先查詢本地是否已經(jīng)有了IServiceManager,如果沒有則新建一個(gè)。
最終則是調(diào)用到了ServiceManagerProxy.getService了
public IBinder getService(String var1) throws RemoteException {
Parcel var2 = Parcel.obtain();
Parcel var3 = Parcel.obtain();
var2.writeInterfaceToken("android.os.IServiceManager");
var2.writeString(var1);
this.mRemote.transact(1, var2, var3, 0);
IBinder var5 = var3.readStrongBinder();
var3.recycle();
var2.recycle();
return var5;
}
該函數(shù)分為以下3部分
- 準(zhǔn)備數(shù)據(jù)。也就是通過Parcel打包數(shù)據(jù)
- IBinder.transact,利用IBinder的transact將請(qǐng)求發(fā)送出去,而不用理會(huì)Binder驅(qū)動(dòng)的open,mmap以及一大堆具體的 Binder協(xié)議中的命令。所以這個(gè)IBinder一定會(huì)在內(nèi)部使用
ProcessState和IPCThreadState來與Binder驅(qū)動(dòng)進(jìn)行通訊。 - 獲取結(jié)果。
上面transact后,我們就可以直接獲取到結(jié)果了。如果大家用過socket,就知道這是一種阻塞式的函數(shù)調(diào)用。因?yàn)樯婕暗竭M(jìn)程間通信,結(jié)果并不是馬上就能獲取到,所以Binder驅(qū)動(dòng)一定要先將調(diào)用者線程掛起,直到有了結(jié)果才把它喚醒。
那么IBinder內(nèi)部是怎么實(shí)現(xiàn)的呢?
2.2 IBinder內(nèi)部
前面我們的IBinder對(duì)象是通過BinderInternal.getContextObject()獲取到的
而它則是一個(gè)native方法
public static final native IBinder getContextObject();
因?yàn)楹虰inder驅(qū)動(dòng)打交道,最終都得通過JNI調(diào)用本地代碼來實(shí)現(xiàn)。
而在native層中g(shù)etContextObject方法通過ProcessState把 創(chuàng)建的對(duì)象BpBinder轉(zhuǎn)換為Java層的IBinder對(duì)象。
IBinder只是一個(gè)接口類,
在native層,IBinder實(shí)現(xiàn)類為BpBinder(由ProcessState創(chuàng)建)
而在Java層,IBinder實(shí)現(xiàn)類則是BinderProxy。
前面調(diào)用IBinder.transact內(nèi)部調(diào)用流程

發(fā)現(xiàn)繞了個(gè)大圈子,最終處理用戶的Binder請(qǐng)求還是通過IPCThreadState和ProcessState來實(shí)現(xiàn)的。
2.3 ProcessState
關(guān)鍵點(diǎn)在于
- 保證同一個(gè)進(jìn)程中只有一個(gè)ProcessState實(shí)例存在,而且只有在ProcessState對(duì)象創(chuàng)建時(shí)才打開Binder設(shè)置(open_driver)以及做內(nèi)存映射(mmap)
- 向上層提供IPC服務(wù)
- 與IPCThreadState分工合作,各司其職
可以看到ProcessState它是一個(gè)進(jìn)程中的單實(shí)例,而IPCThreadState則是線程中的單實(shí)例。
可以說,IPCThreadState負(fù)責(zé)與Binder驅(qū)動(dòng)進(jìn)行具體的命令交互,因而它的transact函數(shù)非常重要,
而ProcessState只是負(fù)責(zé)打開了Binder節(jié)點(diǎn)并做mmap
三.Binder Client客戶端
Binder的最大消費(fèi)者是JAVA層的應(yīng)用程序。一般情況下他們可以在程序代碼的任何位置通過bindService,startActivity以及sendBroadcast等一系列接口方法來實(shí)現(xiàn)與其他進(jìn)程的交互。
有了Binder驅(qū)動(dòng),Service Manager的努力,以及Android系統(tǒng)專門面向應(yīng)用開發(fā)提供的Binder強(qiáng)有力的封裝,才能使應(yīng)用程序之間順利地進(jìn)行無縫通信。
3.1 例子bindService
應(yīng)用程序如何能依托bindService來啟動(dòng)系統(tǒng)中其他進(jìn)程提供的Service呢
①應(yīng)用程序填寫Intent,調(diào)用bindService發(fā)出請(qǐng)求
②收到請(qǐng)求的bindService(此時(shí)還在應(yīng)用程序的運(yùn)行空間中)將與ActivityManagerService(AMS)取得聯(lián)系。根據(jù)前面的分析,為了獲得AMS的Binder句柄,我們還要事先調(diào)用ServiceManager.getService,這里就涉及到進(jìn)程間通信了。在得到AMS的句柄值后,程序才能真正地向它發(fā)起請(qǐng)求。
③AMS基于特定的最優(yōu)匹配策略,從其內(nèi)部存儲(chǔ)的系統(tǒng)所有服務(wù)組件的資料中找到與Intent最匹配的一個(gè),然后向它發(fā)送Service綁定請(qǐng)求。如果目標(biāo)進(jìn)程還不存在的話,AMS還要負(fù)責(zé)把它啟動(dòng)起來。
④被綁定的服務(wù)進(jìn)程需要響應(yīng)綁定,執(zhí)行具體的操作,并在成功完成后通知AMS,然后由AMS再回調(diào)發(fā)起請(qǐng)求的應(yīng)用程序(回調(diào)接口是ServiceConnection)
當(dāng)Activity調(diào)用bindService時(shí),最終調(diào)用到的是ContextImpl.bindService
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
...
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
...
}
那么,應(yīng)用程序又是如何找到AMS并與之建立聯(lián)系的呢?
和ServiceManager一樣,AMS也同樣提供了ActivityManagerNative和ActivityManagerProxy代理
//ActivityManagerNative.getDefault()
static public IActivityManager getDefault() {
return gDefault.get();
}
這個(gè)gDefault.get又是什么
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
...
IActivityManager am = asInterface(b);
...
return am;
}
};
可以看到這里是通過單例模式來創(chuàng)建一個(gè)IActivityManager對(duì)象。
之后通過ServiceManager.getService("activity")方法取得ActivityManagerService的IBinder對(duì)象。
接著調(diào)用asInterface,通過這個(gè)IBinder創(chuàng)建一個(gè)可用的ActivityManagerProxy
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
此外,ActivityManagerNative的另一個(gè)作用是為ActivityManagerService的實(shí)現(xiàn)提供便利。AMS只需要繼承自ActivityManagerNative就可以將用戶的業(yè)務(wù)請(qǐng)求碼與自己的內(nèi)部實(shí)現(xiàn)函數(shù)連接起來。

四.AIDL——Android接口描述語言
它是用于定義客戶端/服務(wù)端通信接口的一種描述語言。
要知道Server Manager本身也是一個(gè)BinderServer,AMS,WMS也是一個(gè)BinderServer,那么從Service Manager的實(shí)現(xiàn)來看,構(gòu)建一個(gè)Binder Server所需的工作為:
1.啟動(dòng)的時(shí)機(jī)
比如SM是開機(jī)的時(shí)候通過init.rc文件啟動(dòng)的,這就保證了它是系統(tǒng)中第一個(gè)注冊成服務(wù)大管家的Server,而WMS,AMS這些則是在SystemServer中啟動(dòng)的。
2.提供一致的服務(wù)接口
一個(gè)Binder Server應(yīng)該向公眾暴露它所能提供的服務(wù),而且客戶端使用的服務(wù)接口和服務(wù)器實(shí)現(xiàn)的服務(wù)接口必須是完全一致的。
對(duì)于WMS
通過分析aidl文件以及由它轉(zhuǎn)換生成的java接口文件,我們知道一個(gè)AIDL接口包括了IwindowManager,IWindowManager.Stub和IWindowManagerManager.Stub.Proxy三個(gè)重要類。
后兩者分別面向與WMS的服務(wù)端和Binder Client本地代理的實(shí)現(xiàn),且都繼承與IWindowManager,因而就保證了Client和Server是在完全一致的服務(wù)接口上進(jìn)行通訊。
3.與Binder驅(qū)動(dòng)的交互
一個(gè)Binder Server需要與Binder驅(qū)動(dòng)做哪些交互呢?除去一系列必要的初始化以外(open,mmap等),就是要通過不斷地ioctl來循環(huán)讀寫數(shù)據(jù)。
比如SM就是通過binder_loop函數(shù)中的一個(gè)for死循環(huán)來完成這一工作的。
而對(duì)于AMS,PMS這些,他們在SystemServer啟動(dòng)的過程中會(huì)開啟一個(gè)線程來循環(huán)讀取消息,這點(diǎn)和binder_loop的主體框架基本一致。
4.外界如何才能訪問到這個(gè)Server服務(wù)?
- ①Service在ServiceManager中注冊
這種方法普遍存在于Android系統(tǒng)服務(wù)中,如ActivityManagerService,WindowManagerService等都在ServiceManager中做了注冊。調(diào)用者只需要通過ServiceManager.getService(name)就可以獲取到Binder Server的本地代理,然后與之通信。
WMS可以通過addService把自己注冊到Service Manager中。因而任何Binder Client都可以通過SM的getService接口獲取到它的一個(gè)引用。稱為實(shí)名的Server。
- ②通過其他Server作為中介
也就是Binder Server不需要在ServiceManager中注冊,只需要通過一個(gè)第三方的實(shí)名Server。
比如WindowSession。
匿名Server安全性高。
更簡單的來構(gòu)建Binder Server就是使用AIDL.