這不是一篇詳細(xì)介紹 Binder 實(shí)現(xiàn)原理的文章,因?yàn)榻榻B Binder 的相關(guān)文章已經(jīng)非常多了,比如 :
Android深入淺出之Binder機(jī)制
Android Bander設(shè)計(jì)與實(shí)現(xiàn) - 設(shè)計(jì)篇
Android Binder機(jī)制系列文章
但是作為一個(gè)普通的 Android 程序員,尤其是不熟悉 C語(yǔ)言,Linux內(nèi)核及驅(qū)動(dòng),JNI 的程序員,面對(duì)大量的底層源碼分析,還是多次中途放棄。
這次終于一鼓作氣看完了 Android Binder機(jī)制系列文章,總算搞清了 Binder 的來(lái)龍去脈,所以這里整理記錄下來(lái)。如果你也想徹底搞清 Binder 的設(shè)計(jì)與實(shí)現(xiàn),那么可以Android Binder機(jī)制系列文章為主進(jìn)行學(xué)習(xí),遇到困惑的地方可以參考本文,說(shuō)不定會(huì)有幫助。
2 源碼及工具準(zhǔn)備
2.1 源碼下載
我們的目的只是為了查看 Binder 源碼,所以不需要安裝 repo,也不用下載整個(gè)的 AOSP 項(xiàng)目,只要下載一些我們會(huì)用到的源碼就好了。
所有的Android的源碼都可以在這里下載 https://android.googlesource.com/
下面列出 Binder學(xué)習(xí)中需要用到的幾個(gè)包:
- platform/frameworks/native Binder體系的主要源碼都在這里了,除了內(nèi)核中的Binder驅(qū)動(dòng)部分
- kernel/common 內(nèi)核中的 Binder驅(qū)動(dòng)部分的源碼就在這里面了
- platform/frameworks/av 包含MediaPlayerService相關(guān)源碼
下載方法:點(diǎn)擊上面鏈接,打開(kāi)后選擇任意一個(gè)分支,點(diǎn)擊tgz鏈接,就可以下載源碼壓縮包了。有些源碼已經(jīng)跟很多博客中分析的不一樣了,不過(guò)改動(dòng)都不大。一般下載master分支就可以了,不過(guò) kernel/common 的master分支是空的,可選擇 android-4.4 分支下載。

2.2 源碼閱讀工具
在閱讀 Binder 源碼時(shí),經(jīng)常需要查看各種方法的調(diào)用,類的定義等等,需要頻繁的查找和跳轉(zhuǎn),所以一個(gè)順手的工具可以大大提高閱讀效率。
推薦使用 Sublime Text 3,mac/windows通吃。裝好之后還需要安裝 Ctags 插件,用于建立其代碼索引,可以方便的跳轉(zhuǎn)查看方法的實(shí)現(xiàn)。
常用操作:
- Ctrl + P,輸入文件名稱,回車打開(kāi)文件
- Ctrl + P,輸入 @+函數(shù)名,查找某個(gè)函數(shù)
3 Binder 概述
3.1 什么是 Binder
在不同的上下文環(huán)境中提到 binder,代表的意思也不同:
- 從 Android 系統(tǒng)層面來(lái)說(shuō),binder 指的一種實(shí)現(xiàn)進(jìn)程間通訊的機(jī)制
- 在 Linux 內(nèi)核中, binder 指的是一個(gè)虛擬設(shè)備的驅(qū)動(dòng),可以想象成兩個(gè)進(jìn)程間通訊的管道,用戶態(tài)的進(jìn)程 A 只需要通過(guò)系統(tǒng)調(diào)用向 binder 驅(qū)動(dòng)發(fā)送命令,binder 驅(qū)動(dòng)就會(huì)搞定一切,把命令傳送給指定的進(jìn)程 B,并把處理結(jié)果返回給 A。 binder 封裝了底層對(duì)線程、內(nèi)存復(fù)雜的管理操作,暴露給用戶進(jìn)程的只是幾個(gè)命令,極大的簡(jiǎn)化了進(jìn)程間的通訊。
3.2 Binder 整體架構(gòu)
Binder 的設(shè)計(jì)整體上是典型的 C/S 架構(gòu),Binder 架構(gòu)中的4個(gè)角色完全可以拿典型的 TCP/IP 網(wǎng)絡(luò)結(jié)構(gòu)來(lái)類比:
- Binder Client:發(fā)起服務(wù)請(qǐng)求的客戶端
- Binder Server:響應(yīng)服務(wù)請(qǐng)求的服務(wù)端
- ServiceManager:提供查找服務(wù),添加服務(wù)的DNS
- Binder 驅(qū)動(dòng):定義通訊協(xié)議,完成數(shù)據(jù)的封裝和傳輸?shù)腡CP/IP通訊協(xié)議
3.3 Binder 典型交互
- Server 將自己注冊(cè)到 ServiceManager 中
- Client 通過(guò)服務(wù)名稱向 ServiceManager 查找對(duì)應(yīng)服務(wù)
- ServiceManager 根據(jù)服務(wù)名稱查找到 Server ,在內(nèi)核中建立對(duì)應(yīng)的 Binder 實(shí)體,并將該實(shí)體對(duì)應(yīng)的 Binder 引用返回給Client
- Client 通過(guò) Binder 引用向 Server 發(fā)起請(qǐng)求
- Binder 驅(qū)動(dòng)根據(jù) Binder 引用找到對(duì)應(yīng)的 Binder 實(shí)體,將客戶端的請(qǐng)求發(fā)送給 Binder 實(shí)體處理
- Binder 驅(qū)動(dòng)將處理后的結(jié)果返回給 Client
接下來(lái)將對(duì) Binder 架構(gòu)中的關(guān)鍵環(huán)節(jié)的流程進(jìn)行一一個(gè)梳理
4 ServiceManager
ServiceManager 作為注冊(cè)和查找服務(wù)的中心,其實(shí)本質(zhì)上也是一個(gè)特殊的 server,只是它必須要先于其他的 server 啟動(dòng),這樣其他的 server 在初始化的時(shí)候就可以把自己注冊(cè)到 ServiceManager 中。
通過(guò)在 init.rc 添加啟動(dòng)腳本,系統(tǒng)在啟動(dòng)初始化時(shí)就會(huì)調(diào)用 service_manager 的 main 入口函數(shù)完成 ServiceManager 的啟動(dòng)和初始化:
platform/native/cmds/servicemanager/service_manager.c
int main()
{
struct binder_state *bs;
bs = binder_open(128*1024); //1.打開(kāi) binder 驅(qū)動(dòng),獲取文件描述符
// 略
if (binder_become_context_manager(bs)) { // 2.將 ServiceManager 注冊(cè)成為“DNS”
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
// 略
binder_loop(bs, svcmgr_handler); // 3.進(jìn)入循環(huán)等待接收客戶端發(fā)來(lái)的請(qǐng)求
return 0;
}
略去無(wú)用代碼,關(guān)鍵的部分只有三步,注釋已經(jīng)寫(xiě)明,下面看看每一步具體做了什么
4.1 binder_open()
platform/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
...
bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC); 1. 打開(kāi) binder 設(shè)備驅(qū)動(dòng)
...
}
...
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); // 2.建立內(nèi)存映射
}
return bs;
}
open 函數(shù)是一個(gè)系統(tǒng)函數(shù),用于打開(kāi)第一個(gè)參數(shù)指明的設(shè)備,對(duì)應(yīng)的函數(shù)在 binder 驅(qū)動(dòng)* /kernel/common/drivers/android/binder.c*(注意跟 servicemanager 目錄下的binder.c區(qū)分,后者只是封裝了一些 servicemanager 跟 binder 驅(qū)動(dòng)交互的操作)的源碼中定義
kernel/common/drivers/android/binder.c
static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
};
這個(gè)結(jié)構(gòu)體定義了open 函數(shù)對(duì)應(yīng)的函數(shù)指針,所以實(shí)際的函數(shù)是 binder_open,這里不展開(kāi)了主要是理清流程。
接下來(lái) mmap 操作完成用戶內(nèi)存到內(nèi)核內(nèi)存的映射。
4.2 binder_become_context_manager()
該函數(shù)內(nèi)部通過(guò) ioctl 函數(shù)向 binder 驅(qū)動(dòng)發(fā)送一個(gè) BINDER_SET_CONTEXT_MGR 的命令,使當(dāng)前進(jìn)程成為系統(tǒng)的 ServiceManager。該命令的處理在 * /kernel/common/drivers/android/binder.c* 的 binder_ioctl 函數(shù)中,binder 驅(qū)動(dòng)會(huì)為建立 ServiceManager 對(duì)應(yīng)的 binder 實(shí)體。(注意:這里的實(shí)現(xiàn)已經(jīng)跟多數(shù)文章中講的不同,不再是用一個(gè)全局變量保存該 binder 實(shí)體,而是保存在 binder_proc->binder_context->binder_context_mgr_node這個(gè)變量中)
4.3 binder_loop()
platform/native/cmds/servicemanager/binder.c
void binder_loop(struct binder_state *bs, binder_handler func)
{
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) {
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
}
}
主要的操作就只有上面幾行代碼,其余的都已省略。
binder_write函數(shù)會(huì)調(diào)用 ioctl 發(fā)送 BC_ENTER_LOOPER 命令告訴 binder 驅(qū)動(dòng)當(dāng)前線程已進(jìn)入消息循環(huán)狀態(tài)。接下來(lái)的死循環(huán),從 binder 驅(qū)動(dòng)讀取消息到 &bwr,如果沒(méi)有消息就會(huì)阻塞直到被喚醒,讀取到消息后再調(diào)用binder_parse解析 &bwr 中的消息內(nèi)容。
binder_parse會(huì)調(diào)用 func 函數(shù)處理請(qǐng)求。func 參數(shù)傳入的值是一個(gè)指向svcmgr_handler函數(shù)的函數(shù)指針,所以具體的如添加查找函數(shù)的請(qǐng)求處理主要都在 svcmgr_handler函數(shù)中了。
處理完請(qǐng)求回到binder_parse 后調(diào)用binder_send_reply向驅(qū)動(dòng)返回處理的結(jié)果(根據(jù)請(qǐng)求類型如果不需要回復(fù)就沒(méi)有這一步)
5 獲取 ServiceManager
客戶端想要獲取系統(tǒng)服務(wù),首先就要向 ServiceManager 請(qǐng)求服務(wù)端的代理對(duì)象,而各類系統(tǒng)服務(wù) 也要在系統(tǒng)啟動(dòng)時(shí)先注冊(cè)到 ServiceManager。所以如何獲取 ServiceManager 就成為了第一個(gè)要解決的問(wèn)題。
IServiceManager::defaultServiceManager() 就是用來(lái)獲得一個(gè) ServiceManager 服務(wù)代理的函數(shù)。
platform/native/libs/binder/IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
一個(gè)典型的單例模式,關(guān)鍵就是下面這一句了,信息量很大,一點(diǎn)一點(diǎn)拆開(kāi)來(lái)看
gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));```
###5.1 ProcessState::self()
這里又是一個(gè)單例模式獲取一個(gè) `ProcessState` 對(duì)象,在構(gòu)造函數(shù)中,打開(kāi)了 `/dev/binder` 設(shè)備,保存了文件句柄。然后調(diào)用mmap()映射內(nèi)存到當(dāng)前進(jìn)程的虛擬地址空間。
###5.2 getContextObject()
實(shí)際上調(diào)用了 `getStrongProxyForHandle(handle)`,這個(gè)函數(shù)返回一個(gè) BpBinder(handle),這里 handle 為0,也即 ServiceManager 的句柄值。
###5.3 interface_cast<IServiceManager>
這部分是最暗藏玄機(jī)也比較不好理解的部分,前面我們已經(jīng)獲得了一個(gè) BpBinder 對(duì)象,而這里最終要返回一個(gè) IServiceManager 對(duì)象,然而這兩者并沒(méi)有任何的繼承關(guān)系,所以肯定不是簡(jiǎn)單的強(qiáng)轉(zhuǎn)。看這個(gè)模板函數(shù)的定義。
frameworks/native/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
把 `INTERFACE` 替換成 `IServiceManager`,然而 `IServiceManager` 中并沒(méi)有 `asInterface` 這個(gè)方法。注意到 *IServiceManager.h* 中有一句宏調(diào)用:
DECLARE_META_INTERFACE(ServiceManager)
而 *IServiceManager.cpp* 中也有一句宏調(diào)用:
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
這里的聲明和實(shí)現(xiàn)里有包括了 asInterface 方法,這兩個(gè)宏定義在 IInterface.h 中:
frameworks/native/include/binder/IInterface.h
define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { }
把兩個(gè)宏展開(kāi)之后就變成了:
define DECLARE_META_INTERFACE(IServiceManager) \
static const android::String16 descriptor; \
static android::sp<IServiceManager> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
IServiceManager(); \
virtual ~IServiceManager(); \
define IMPLEMENT_META_INTERFACE(IServiceManager, "android.os.IServiceManager") \
const android::String16 IServiceManager::descriptor("android.os.IServiceManager"); \
const android::String16& \
IServiceManager::getInterfaceDescriptor() const { \
return IServiceManager::descriptor; \
} \
android::sp<IServiceManager> IServiceManager::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<IServiceManager> intr; \
if (obj != NULL) { \
intr = static_cast<IServiceManager*>( \
obj->queryLocalInterface( \
IServiceManager::descriptor).get()); \
if (intr == NULL) { \
intr = new BpServiceManager(obj); \
} \
} \
return intr; \
} \
IServiceManager::IServiceManager() { } \
IServiceManager::~IServiceManager() { }
我們重點(diǎn)關(guān)注 `asInterface` 方法,這里傳入的 `obj` 參數(shù)就是前面得到的 `BpBinder(0)` 對(duì)象,`queryLocalInterface` 的默認(rèn)實(shí)現(xiàn)在 *IBinder.cpp* 中,它返回 null,所以這里 `intr == null`,最終就構(gòu)造了 `BpServiceManager(obj)` 返回,而`BpServiceManager` 正是 `IServiceManager` 的一個(gè)實(shí)現(xiàn)類,它也是 ServiceManager 在客戶端的代理對(duì)象。
###5.4 總結(jié)
借用 [這篇文章](http://wangkuiwu.github.io/2014/09/01/Binder-Introduce/#anchor2_1_2) 的一張圖來(lái)梳理一下 Binder 架構(gòu)中各個(gè)類的關(guān)系:

1. 服務(wù)接口定義服務(wù)提供的業(yè)務(wù)邏輯,比如 IServiceManager,定義了 getService,addService 等。
2. 本地服務(wù),也即服務(wù)端,是真正實(shí)現(xiàn)業(yè)務(wù)邏輯的對(duì)象。
3. 遠(yuǎn)程服務(wù),也即客戶端,或者代理端,比如 BpServiceManager,里面保存了一個(gè) BpBinder(實(shí)際在構(gòu)造函數(shù)時(shí)保存在父類 `BpRefBase.mRemote` 中,`通過(guò) remote()` 方法獲得),作為服務(wù)端的代理,主要職責(zé)是封裝請(qǐng)求,并向 Binder 驅(qū)動(dòng)發(fā)起請(qǐng)求,Binder 驅(qū)動(dòng)會(huì)負(fù)責(zé)把請(qǐng)求發(fā)送到對(duì)應(yīng)的服務(wù)端。這部分后面還會(huì)再做講解
4. Binder 驅(qū)動(dòng)收到代理發(fā)起的請(qǐng)求,最終會(huì)調(diào)用到 BBinder.onTransact 方法,所以本地服務(wù)只要實(shí)現(xiàn) onTransact 方法就能處理客戶端發(fā)來(lái)的請(qǐng)求了,這部分后面還會(huì)再做講解。
5. BpInterface<INTERFACE> 和 BnInterface<INTERFACE> 都定義在 Interface.h 中,這里的 INTERFACE 即是服務(wù)接口。
# 6 注冊(cè)服務(wù)到ServiceManager
獲取到 IServiceManager,就可以調(diào)用其 addService 方法,將服務(wù)添加到 ServiceManager 了,注意這時(shí)候服務(wù)扮演的是客戶端的角色,ServiceManager 扮演的是服務(wù)端的角色。
### 6.1 addService
platform/native/libs/binder/IServiceManager.BpServiceManager
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
可以看到這里把請(qǐng)求的參數(shù)打包到 Parcel 中(關(guān)于 Parcel 打包數(shù)據(jù)的原理這里就不具體講了,可以參考[這里](http://wangkuiwu.github.io/2014/09/05/BinderCommunication-AddService01)),注意 `data.writeStrongBinder(service);` 這句,這里的 service 是一個(gè) BnXXX,也即一個(gè)本地服務(wù)對(duì)象,在寫(xiě)入的時(shí)候會(huì)被轉(zhuǎn)換為一個(gè) flat_binder_object 結(jié)構(gòu)體寫(xiě)入,關(guān)于這個(gè)結(jié)構(gòu)體的說(shuō)明,參見(jiàn) [這里](http://wangkuiwu.github.io/2014/09/02/Binder-Datastruct/#anchor1_7)。
接下來(lái)`remote()->transact()`,這里的 remote() 前面已經(jīng)說(shuō)了,返回之前保存進(jìn)去的 BpBinder,BpBinder 的 transact 方法最終調(diào)用到 `IPCThreadState::self()->transact()`,到這里,實(shí)際跟 binder 驅(qū)動(dòng)打交道的類 `IPCThreadState 終于出現(xiàn)了。
### 6.2 IPCThreadState.transact()
`IPCThreadState::self()` 獲取調(diào)用進(jìn)程的 IPCThreadState 的單例,如果首次調(diào)用,會(huì)進(jìn)行打開(kāi)binder驅(qū)動(dòng),內(nèi)存映射等操作,和前面ServiceManager的啟動(dòng)類似。
精簡(jiǎn)后保留主要邏輯的 transact() 代碼:
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck();
if (err == NO_ERROR) {
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
err = waitForResponse(reply);
}
}
return err;
}
可以看到主要涉及兩個(gè)函數(shù) `writeTransactionData`,`waitForResponse`
### 6.3 writeTransactionData()
這里必須先介紹 IPCThreadState 兩個(gè) Parcel 類型的成員變量,mIn 和 mOut,分別用來(lái)保存從 binder 驅(qū)動(dòng)讀取的數(shù)據(jù)和即將向 binder 驅(qū)動(dòng)寫(xiě)入的數(shù)據(jù)。而 `writeTransactionData()` 這個(gè)函數(shù)的作用就是把數(shù)據(jù)二次封裝到 mOut 中,這里又必須借一張圖來(lái)說(shuō)明了:

有效數(shù)據(jù)對(duì)應(yīng)傳入的 data 參數(shù),也就是在6.1節(jié)封裝的那個(gè) Parcel,而經(jīng)過(guò)`writeTransactionData()` 的再次封裝之后, mOut = binder_transaction_data 結(jié)構(gòu) + BC_TRANSACTION(一個(gè)整數(shù)值)。后面會(huì)看到在發(fā)給 binder 驅(qū)動(dòng)之前數(shù)據(jù)還會(huì)經(jīng)過(guò)一層封裝到 `binder_write_read` 結(jié)構(gòu)中。
###6.4 waitForResponse()
精簡(jiǎn)后保留主要邏輯的代碼:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;
default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
這里的邏輯相對(duì)復(fù)雜,不過(guò)整體上看,主要是一個(gè)死循環(huán),當(dāng)滿足某些特定條件時(shí)才會(huì)跳出,下面具體分析死循環(huán)里的幾個(gè)關(guān)鍵步驟。
####6.4.1 第一次調(diào)用talkWithDriver()
精簡(jiǎn)后的代碼如下:
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
binder_write_read bwr;
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
// We don't want to write anything if we are still reading
// from data left in the input buffer and the caller
// has requested to read the next data.
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data(); /*****第1步*****/
// This is what we'll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
#if defined(__ANDROID__) /*****第2步*****/
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
} while (err == -EINTR);
if (err >= NO_ERROR) { /*****第3步*****/
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
return NO_ERROR;
}
return err;
}
代碼看起來(lái)很長(zhǎng),但是其實(shí)主要就分為一下幾步,已在代碼中標(biāo)出:
1. 把數(shù)據(jù)包裝到一個(gè) ` binder_write_read` 結(jié)構(gòu)的變量 `bwr` 中
2. 調(diào)用 `ioctl` 向binder驅(qū)動(dòng)發(fā)送指令,binder驅(qū)動(dòng)會(huì)從 `bwr` 的 `write_buffer` 讀取數(shù)據(jù),經(jīng)過(guò)處理之后,如果有返回,就寫(xiě)入到 `read_buffer` 中
3. 根據(jù) `bwr` 中的數(shù)據(jù)更新 `mOut` 和 `mIn` 的數(shù)據(jù)
**注:**這里的第2步這里只是一筆帶過(guò),其實(shí)包含了和binder驅(qū)動(dòng)的交互的關(guān)鍵步驟,為了避免打斷分析的流程,這里就不深入了,具體可以參考
[Android Binder機(jī)制(五) addService詳解01之 請(qǐng)求的發(fā)送](http://wangkuiwu.github.io/2014/09/05/BinderCommunication-AddService01/),
[Android Binder機(jī)制(六) addService詳解02之 請(qǐng)求的處理](http://wangkuiwu.github.io/2014/09/05/BinderCommunication-AddService02/),
[Android Binder機(jī)制(七) addService詳解03之 請(qǐng)求的反饋](http://wangkuiwu.github.com/2014/09/05/BinderCommunication-AddService03/)
這三篇文章。這里我們只需要知道,binder驅(qū)動(dòng)把請(qǐng)求發(fā)送給 ServiceManager后,就返回了 BR_NOOP 和 BR_TRANSACTION_COMPLETE 兩條指令,注意這里返回時(shí)只代表驅(qū)動(dòng)已經(jīng)把請(qǐng)求發(fā)送給 ServiceManager處理,而處理的結(jié)果此時(shí)還沒(méi)返回。
####6.4.2 讀取 BR_NOOP 和 BR_TRANSACTION_COMPLETE
上一節(jié)第一次調(diào)用talkWithDriver()后,收到了binder驅(qū)動(dòng)返回的 BR_NOOP 和 BR_TRANSACTION_COMPLETE 兩條指令,回到`waitForResponse()`的死循環(huán),接著循環(huán)兩次從`mIn`中讀取兩條指令,這兩條指令都是什么都不做。
####6.4.3 進(jìn)入中斷等待
讀取完兩條返回的指令后,再次進(jìn)入 `waitForResponse()` 的死循環(huán),此時(shí):
bwr.write_size = 0;
bwr.write_buffer = (long unsigned int)mOut.data();
bwr.write_consumed = 0;
bwr.read_size = mIn.dataCapacity(); // 256字節(jié)
bwr.read_buffer = (long unsigned int)mIn.data();
bwr.read_consumed = 0;
再次進(jìn)入 talkWithDriver()->ioctl(),此時(shí)因?yàn)閎wr.write_size = 0 代表沒(méi)有數(shù)據(jù)要寫(xiě)入,然后bwr.read_consumed = 0 代表沒(méi)有數(shù)據(jù)要讀取,此時(shí)就會(huì)進(jìn)入中斷等待狀態(tài),具體查看 binder驅(qū)動(dòng)源碼中 binder_thread_read() 方法的實(shí)現(xiàn)。
###6.5 總結(jié)
概括起來(lái),向binder發(fā)起一個(gè)請(qǐng)求的過(guò)程主要包括:
1. 數(shù)據(jù)的層層封裝,Parcel --> binder_transaction_data --> binder_write_read
2. 通過(guò) IPCThreadState.transact() --> waitForResponse() --> talkWithDriver() --> ioctl() 向binder驅(qū)動(dòng)發(fā)起請(qǐng)求
3. binder驅(qū)動(dòng)會(huì)按照先寫(xiě)后讀的順序處理請(qǐng)求,喚醒服務(wù)端的進(jìn)程處理請(qǐng)求,同時(shí)向客戶端返回 BR_TRANSACTION_COMPLETE 代表已經(jīng)將客戶端的請(qǐng)求發(fā)送給服務(wù)端
4. 如果客戶端沒(méi)有別的請(qǐng)求,就陷入中斷等待
5. 服務(wù)端處理完請(qǐng)求,又將跟 binder 驅(qū)動(dòng)通訊,binder驅(qū)動(dòng)將喚醒客戶端,并把處理結(jié)果返回給客戶端
#7 The End
關(guān)于 binder 機(jī)制的整體流程的總結(jié)總算寫(xiě)完了,其中還涉及很多細(xì)節(jié)沒(méi)有涵蓋,不過(guò)作為一個(gè)備忘,起碼以后再看起來(lái),可以很快的理清思路,再需要找到實(shí)現(xiàn)細(xì)節(jié)也不難了。最后還是要感謝 [Android Binder機(jī)制系列文章](http://wangkuiwu.github.io/2014/09/01/Binder-Introduce/) 的作者,寫(xiě)的真是不能再詳細(xì)了!