如果帶著問題去學(xué)習(xí)binder又是怎樣的呢?
1. 第一個(gè)binder線程 Binder:PID_1是怎樣創(chuàng)建的
在App進(jìn)程創(chuàng)建的時(shí)候
nativeZygoteInit
-> com_android_internal_os_RuntimeInit_nativeZygoteInit
-> onZygoteInit
-> ProcessState
-> startThreadPool()
-> spawnPooledThread(true)
isMain=true
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName(); //這里是第一個(gè)binder 線程,也就是binder主線程
sp<Thread> t = new PoolThread(isMain); //生成一個(gè)線程
t->run(name.string()); //線程運(yùn)行,不停的調(diào)用theadLoop
}
}
virtual bool threadLoop()
{
IPCThreadState* ptr = IPCThreadState::self();
if (ptr) {
ptr->joinThreadPool(mIsMain);
}
return false; //threadLoop返回false表示會(huì)退出線程,即線程結(jié)束了
}
void IPCThreadState::joinThreadPool(bool isMain)
{
// mOut是寫入內(nèi)核的數(shù)據(jù),如果是Main Binder線程,則發(fā)送 BC_ENTER_LOOPER
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
processPendingDerefs(); //處理引用計(jì)數(shù)
result = getAndExecuteCommand(); //獲得命令并執(zhí)行
//異常退出
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
abort();
}
//如果timeout了,但如果不是 Main Binder線程也就是非 Binder:xxx_1線程就直接退出
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
//通知binder驅(qū)動(dòng) 線程要退出了
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
在 binder_thread_write 中會(huì)有對 BC_ENTER_LOOPER的處理, 如下所示,thread是指binder_thread,也就是當(dāng)前線程的描述符, 將BINDER_LOOPER_STATE_ENTERED保存到 binder_thread的looper變量里.
looper變量主要保存的binder線程的一種狀態(tài)如
- BINDER_LOOPER_STATE_REGISTERED
標(biāo)記該binder線程是非主binder線程 - BINDER_LOOPER_STATE_ENTERED
標(biāo)記該binder線程是主binder線程 - BINDER_LOOPER_STATE_EXITED
標(biāo)記該binder線程馬上就要退出了 - BINDER_LOOPER_STATE_INVALID
標(biāo)記是無效的,但是這個(gè)并沒有實(shí)際用處,一般是 原來是主線程,然后用戶態(tài)又通過主線程發(fā)送了BC_REGISTER_LOOPER,就會(huì)標(biāo)志 INVALID, 同理與REGISTER一樣 - BINDER_LOOPER_STATE_WAITING
標(biāo)記當(dāng)前binder線程正在等著client的請求 - BINDER_LOOPER_STATE_NEED_RETURN
這個(gè)標(biāo)志,是當(dāng)前新線程下來在生成binder_thread里置位的,表示該binder線程在處理完transaction后需要返回到用戶態(tài)。
case BC_ENTER_LOOPER:
if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
thread->looper |= BINDER_LOOPER_STATE_INVALID;
binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
proc->pid, thread->pid);
}
thread->looper |= BINDER_LOOPER_STATE_ENTERED;
break;
從上面可知,startThreadPool就是創(chuàng)建APP進(jìn)程的binder線程池模型, 它也會(huì)創(chuàng)建第一個(gè)binder主線程,該線程不會(huì)退出(非 critcal錯(cuò)誤),而spawnPooledThread函數(shù)用于創(chuàng)建一個(gè)普通的binder線程,這些線程都有可能會(huì)退出。
二、 一個(gè)APP里最多能有多少個(gè)binder線程呢? 其它binder線程是怎么創(chuàng)建的,由誰創(chuàng)建的呢?
從第一節(jié)可知,只要調(diào)用 spawnPooledThread()函數(shù)就創(chuàng)建了一個(gè)binder線程,因此從代碼上來看除了第一個(gè)主binder線程由APP用戶態(tài)主動(dòng)創(chuàng)建外,其它的都是由Binder驅(qū)動(dòng)主動(dòng)向APP申請創(chuàng)建,也就是說binder線程的創(chuàng)建是看binder驅(qū)動(dòng)是否很繁忙(這里的繁忙是與本進(jìn)程相關(guān)的),來決定是否需要向APP進(jìn)程申請創(chuàng)建,也就是APP進(jìn)程被動(dòng)創(chuàng)建。
2.1 Server端
其實(shí)也很好理解,binder最終的通信包括client和server雙方。server方并不知道什么時(shí)候會(huì)有client的請求,client的有請求,它就直接丟給binder驅(qū)動(dòng),然后由binder驅(qū)動(dòng)根據(jù)當(dāng)前server的能力(是否有多余線程去處理)去看下是否需要新的線程來處理client的請求。
那試問一個(gè) Server端 App 最多同時(shí)能跑多少個(gè)binder線程呢?
這個(gè)問題,可以簡單的測試一下,寫一個(gè)Service, 然后實(shí)現(xiàn)一個(gè)API里死循環(huán)sleep, 反正就是不返回, 另一個(gè)client在創(chuàng)建多個(gè)非UI線程去請求API, 然后再dump出來,就知道最多支持多少個(gè)binder線程了。
我們從 spawnPooledThread的調(diào)用函數(shù)來看就知道能有多少個(gè)binder線程了。
IPCThreadState::executeCommand(int32_t cmd) {
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
break;
}
executeCommand函數(shù)執(zhí)行從Binder 驅(qū)動(dòng)傳遞到 BR_SPAWN_LOOPER, 這時(shí)就得繼續(xù)從binder驅(qū)動(dòng)中去找 BR_SPAWN_LOOPER了。
static int binder_thread_read(...)
...
if (proc->requested_threads + proc->ready_threads == 0 &&
proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
/*spawn a new thread if we leave this out */) {
proc->requested_threads++;
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
return -EFAULT;
binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
}
}
在binder_thread_read調(diào)用的最后,就會(huì)有可能去spawn一個(gè)線程, 但是也是有條件的, 且要同時(shí)滿足才行
binder_proc -> ready_threads = 0
ready_threads表明當(dāng)前進(jìn)程中還沒有準(zhǔn)備好的線程, 換句話說,當(dāng)前binder線程都有各自的任務(wù)在處理, 沒空接受新的任務(wù)了。binder_proc -> requested_threads = 0
如果 reqeusted_threads >0 表明 binder_driver已經(jīng)通過其它binder線程請求APP進(jìn)程去創(chuàng)建binder線程來處理任務(wù)的路上了, 所以啊,binder驅(qū)動(dòng)就不會(huì)再通知一次了,因?yàn)槿绻偻ㄖ淮?,那么就?huì)創(chuàng)建兩個(gè)binder線程,資源浪費(fèi)嘛。
所以如果 requested_threads = 0,如果其它條件滿足,那就由我這個(gè)binder線程就請求APP去創(chuàng)建另一個(gè)binder線程proc->requested_threads_started < proc->max_threads
max_threads: 這個(gè)是APP進(jìn)程通知binder驅(qū)動(dòng)我這個(gè)APP進(jìn)程當(dāng)前最多只能創(chuàng)建max_threads個(gè)線程,如果我已經(jīng)創(chuàng)建這么多了,不要再通知我去創(chuàng)建了。至于別人(其它APP)想要獲得我的服務(wù)或其它,別急,取號等著,等著我的binder線程不忙了再去處理。thread->looper & (BINDER_LOOPER_STATE_REGISTERED |BINDER_LOOPER_STATE_ENTERED
looper保存著當(dāng)前線程的一些狀態(tài),BINDER_LOOPER_STATE_REGISTERED(非主Binder線程)|BINDER_LOOPER_STATE_ENTERED(主binder線程) 這兩個(gè)是binder線程的標(biāo)志. 即: Binder驅(qū)動(dòng)只有通過我的APP創(chuàng)建的(有效的)binder線程才有資格向我(APP)提出創(chuàng)建其它binder線程.
好了,上面4個(gè)條件同時(shí)滿足了,就通知APP創(chuàng)建一個(gè)新的 binder線程了。
但還有幾個(gè)問題
binder_proc->max_threads最大是多少呢?
在ProcessState.cpp的 open_driver 函數(shù)中, 會(huì)設(shè)置一個(gè)默認(rèn)的最大binder線程數(shù) DEFAULT_MAX_BINDER_THREADS = 15;
但是BinderInternal.java也提供了setMaxThreads去修改Binder驅(qū)動(dòng)中的max_threads值. 比如system_server就設(shè)置了max_threads為31
注意 : BinderInternal是internal的類,APP不能直接調(diào)用。ready_threads 這個(gè)是什么意思呢?
在binder_thread_read函數(shù)中
static int binder_thread_read(..) {
//wait_for_proc_work表示是否需要去等著proc的任務(wù),當(dāng)然前提是這個(gè)binder線程沒有任務(wù)可做了,
//那這個(gè)binder線程就可以向進(jìn)程申請去處理進(jìn)程的其它任務(wù)了
wait_for_proc_work = thread->transaction_stack == NULL &&
list_empty(&thread->todo);
if (wait_for_proc_work)
proc->ready_threads++; //表明當(dāng)前進(jìn)程又多了一個(gè)可用的binder線程去接受任務(wù)了
if (wait_for_proc_work) {
//等著整個(gè)進(jìn)程的任務(wù)
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
} else {
//等著binder線程本身的任務(wù)
ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
}
...
//代碼運(yùn)行到這里就表明有任務(wù)了,那么我這個(gè)binder線程就要去接受任務(wù)去做了,
if (wait_for_proc_work)
//既然我已經(jīng)開始去處理任務(wù)了,那么整個(gè)進(jìn)程當(dāng)前就少了我一個(gè)可用的線程啦
proc->ready_threads--;
...
done:
//決定是否再創(chuàng)建一個(gè)新的binder線程
*consumed = ptr - buffer;
if (proc->requested_threads + proc->ready_threads == 0 &&
proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
proc->requested_threads++; //請求創(chuàng)建線程+1
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
return -EFAULT;
binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
}
}
- requested_threads與requested_threads_started
requested_threads表示要請求創(chuàng)建的線程數(shù),在上面決定創(chuàng)建binder線程后,該值會(huì)+1
而requested_threads_started表示當(dāng)前進(jìn)程已經(jīng)啟動(dòng)吧這么多個(gè)線程,
APP接收到創(chuàng)建新的binder線程的請求后就會(huì)調(diào)用spawnPooledThread(false)去創(chuàng)建一個(gè)非Main的binder線程, 而最后又會(huì)通過joinThreadPool觸發(fā)binder驅(qū)動(dòng)的BC_REGISTER_LOOPER
static int binder_thread_write(...) {
case BC_REGISTER_LOOPER:
if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
thread->looper |= BINDER_LOOPER_STATE_INVALID;
} else if (proc->requested_threads == 0) {
thread->looper |= BINDER_LOOPER_STATE_INVALID;
} else {
//正常情況會(huì)進(jìn)入該分支
proc->requested_threads--; //要請求創(chuàng)建的binder線程數(shù)減1
proc->requested_threads_started++; //啟動(dòng)過的線程數(shù)+1
}
thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
break;

2.2 client
client端作為請求端,是從用戶態(tài)下發(fā)起請求的,所以client一般是自己申請創(chuàng)建線程,然后在線程里去請求 server端的服務(wù),這里不會(huì)涉及到binder線程。
那么client就只有一個(gè)默認(rèn)的主binder線程了么?當(dāng)然不是,從2.1可知,binder驅(qū)動(dòng)會(huì)不管是server,還是client, 都會(huì)默認(rèn)有一個(gè)空閑線程,所以client的主binder線程在binder_thread_read的最后發(fā)現(xiàn)當(dāng)前沒有可ready的線程,這時(shí)就通知client端創(chuàng)建一個(gè)binder線程。所以一般client有兩個(gè)binder線程。
三、Server的binder線程阻塞在哪里了?
人第二節(jié)可知道,Server端的binder線程會(huì)一直等著client的請求,即如果沒有客戶端請求時(shí),binder線程應(yīng)該是一直阻塞著的,那么Server端等在什么地方呢?
來看下binder線程的運(yùn)行過程便可知, 第一小節(jié)已經(jīng)貼出相關(guān)代碼了, 再帖一次,
void IPCThreadState::joinThreadPool(bool isMain)
{
// mOut是寫入內(nèi)核的數(shù)據(jù),如果是Main Binder線程,則發(fā)送 BC_ENTER_LOOPER
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
processPendingDerefs(); //處理引用計(jì)數(shù)
result = getAndExecuteCommand(); //獲得命令并執(zhí)行
//異常退出
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
abort();
}
//如果timeout了,但如果不是 Main Binder線程也就是非 Binder:xxx_1線程就直接退出
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
//通知binder驅(qū)動(dòng) 線程要退出了
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
從joinThreadPool里,有一個(gè)getAndExecuteCommand, 來看下這個(gè)函數(shù)干了些什么吧
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result; //異常處理
cmd = mIn.readInt32(); //獲得從Binder驅(qū)動(dòng)返回來的BR_ 號
...
result = executeCommand(cmd); //開始執(zhí)行相關(guān)命令
...
}
return result;
}
該函數(shù)很簡單,從binder驅(qū)動(dòng)里拿到client要操作的CMD, 然后調(diào)用executeCommand執(zhí)行CMD。
在看 talkWithDriver 之前,先來看下 binder_write_read

binder_write_read是一個(gè)結(jié)構(gòu)體,它主要作用是告訴binder驅(qū)動(dòng)我這次請求的目的是什么,一是read, 另一個(gè)就是write,
- write_size > 0 表明需要往binder驅(qū)動(dòng)寫write_buffer的數(shù)據(jù)
- read_size >0 表明需要往binder驅(qū)動(dòng)讀數(shù)據(jù)放到write_buffer的數(shù)據(jù)
- write_consumed 表明已經(jīng)寫入了多少字節(jié)
- read_consumed 表明讀入了多少字節(jié)
- write_buffer 指向用戶態(tài)下的數(shù)據(jù)地址,其實(shí)也就是IPCThreadState里的mOut (Parcel)里的mData地址
- read_buffer 指向用戶態(tài)下的數(shù)據(jù)地址,其實(shí)也就是IPCThreadState里的mIn (Parcel)里的mData地址
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
binder_write_read bwr;
//mIn.dataPosition()是當(dāng)前mIn中mData的指針,
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
//doReceive默認(rèn)為true, needRead為true表明還需要從Binder驅(qū)動(dòng)中讀取數(shù)據(jù),這時(shí)候就不能往binder驅(qū)動(dòng)中寫數(shù)據(jù)
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
//填充寫數(shù)據(jù)的相關(guān)字段
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
// This is what we'll read.
if (doReceive && needRead) {
//填充讀數(shù)據(jù)相關(guān)字段
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__)
//阻塞式的調(diào)用 binder_ioctl
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD <= 0) {
err = -EBADF;
}
} while (err == -EINTR);
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
//根據(jù)寫了多少數(shù)據(jù),來更新mOut的相關(guān)數(shù)據(jù)
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
//根據(jù)讀了多少數(shù)據(jù),來更新mIn的相關(guān)數(shù)據(jù)
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
return NO_ERROR;
}
return err;
}
3.1 binder線程第一次調(diào)用 binder_ioctl
我們來看下binder線程創(chuàng)建后第一次調(diào)用 binder_ioctl 的情況
從joinThreadPool可以看出, 會(huì)寫入一個(gè) BC_REGISTER_LOOPER
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
因此此時(shí)binder_write_read的結(jié)構(gòu)如下所示

來看下binder驅(qū)動(dòng)是怎么處理的呢
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
// binder_stop_on_user_error默認(rèn)為0,只有條件為false的時(shí)候才會(huì)一直block在這,所以這里并不會(huì)block
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
binder_lock(__func__);
//創(chuàng)建一個(gè)與binder線程相關(guān)的binder_thread, 第一次創(chuàng)建會(huì)設(shè)置thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN
thread = binder_get_thread(proc);
switch (cmd) {
case BINDER_WRITE_READ: //執(zhí)行BINDER_WRITE_READ命令
ret = binder_ioctl_write_read(filp, cmd, arg, thread);
break;
...
}
ret = 0;
err:
if (thread) //這里取消BINDER_LOOPER_STATE_NEED_RETURN
thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
binder_unlock(__func__);
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
err_unlocked:
return ret;
}
其中BINDER_LOOPER_STATE_NEED_RETURN這個(gè)非常重要,就是這個(gè)標(biāo)志,決定了binder線程第一次的走向,如果是第一次進(jìn)來, binder_thread->looper都設(shè)置了該標(biāo)志,而該binder_ioctl返回時(shí),會(huì)將該標(biāo)志取消
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
struct binder_write_read bwr;
//獲得用戶態(tài)的 binder_write_read
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
ret = -EFAULT;
goto out;
}
if (bwr.write_size > 0) {
//有數(shù)據(jù)要寫入,這里就是 BC_REGISTER_LOOPER
ret = binder_thread_write(proc, thread, bwr.write_buffer,
bwr.write_size, &bwr.write_consumed);
}
if (bwr.read_size > 0) {
//有數(shù)據(jù)要讀取
ret = binder_thread_read(proc, thread, bwr.read_buffer,
bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
//如果進(jìn)程描述結(jié)構(gòu)體中有任務(wù)要做時(shí),喚醒等在binder_proc->wait的列表
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
}
//將數(shù)據(jù)拷貝到用戶態(tài)
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
}
out:
return ret;
}
binder線程第一次調(diào)用binder_ioctl也就是寫入一個(gè)BC_REGISTER_LOOPER, 所以 binder_thread_write只是將binder_thread->looper設(shè)置一個(gè)BINDER_LOOPER_STATE_REGISTERED
現(xiàn)在來看下binder_thread_read
static int binder_thread_read(...)
{
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
int ret = 0;
int wait_for_proc_work;
//第一次進(jìn)來 consumed為0,所以進(jìn)入該分支, 會(huì)返回一個(gè) BR_NOOP
if (*consumed == 0) {
if (put_user(BR_NOOP, (uint32_t __user *)ptr)) return -EFAULT;
ptr += sizeof(uint32_t);
}
retry:
//binder線程第一次進(jìn)來,沒有transaction任務(wù),也沒有其它任務(wù),所以waite_for_proc_work為true
wait_for_proc_work = thread->transaction_stack == NULL &&
list_empty(&thread->todo);
thread->looper |= BINDER_LOOPER_STATE_WAITING;
if (wait_for_proc_work)
proc->ready_threads++; //線程可用
binder_unlock(__func__);
if (wait_for_proc_work) { //進(jìn)入該分支
if (non_block) {
if (!binder_has_proc_work(proc, thread))
ret = -EAGAIN;
} else
//如果binder_has_proc_work為false,將會(huì)一直等在這里,直到被喚醒
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
} else {
if (non_block) {
if (!binder_has_thread_work(thread))
ret = -EAGAIN;
} else
ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
}
binder_lock(__func__);
if (wait_for_proc_work)
proc->ready_threads--; //線程接收到任務(wù),準(zhǔn)備執(zhí)行了
thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
if (ret)
return ret;
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
if (!list_empty(&thread->todo)) { //無任務(wù)
w = list_first_entry(&thread->todo, struct binder_work, entry);
} else if (!list_empty(&proc->todo) && wait_for_proc_work) { //無任務(wù)
w = list_first_entry(&proc->todo, struct binder_work, entry);
} else {
/* no data added */
if (ptr - buffer == 4 &&
!(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))
goto retry;
break; //直接break到
}
if (end - ptr < sizeof(tr) + 4)
break;
switch(...) {}
}
done:
//決定是否要向用戶態(tài)申請創(chuàng)建一個(gè)新的線程
*consumed = ptr - buffer;
if (proc->requested_threads + proc->ready_threads == 0 &&
proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
/*spawn a new thread if we leave this out */) {
proc->requested_threads++;
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
return -EFAULT;
binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
}
return 0;
}
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
現(xiàn)在來看下wait_event_freezable_exclusive, 該函數(shù)的條件如果為true,即表明binder有任務(wù)時(shí),就不會(huì)阻塞,而是直接執(zhí)行,binder線程第一次進(jìn)來的時(shí)候(因?yàn)閎inder線程的創(chuàng)建是防止后續(xù)有請求到來,所以當(dāng)前是沒有任務(wù)的), 當(dāng)前沒有任務(wù)的話,binder線程應(yīng)該一直等著呀,為什么這里沒有阻塞式的等呢?
static int binder_has_proc_work(struct binder_proc *proc, struct binder_thread *thread)
{
return !list_empty(&proc->todo) ||
(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
}
哦,原來binder_has_proc_work會(huì)判斷如果binder線程是第一次進(jìn)來的話,也就是設(shè)置了BINDER_LOOPER_STATE_NEED_RETURN,也就是表明該線程不管你有沒有任務(wù),我都需要返回到用戶態(tài),所以這里為true, 也就不會(huì)等待了。
所以第一次返回給用戶態(tài)時(shí),只返回一個(gè) BR_NOOP, 表示無操作
3.2 binder線程第二次調(diào)用 binder_ioctl
3.1 節(jié),mOut已經(jīng)寫完數(shù)據(jù)了,

這里write_size=0, read_size 依然是 256,
只不過第二次進(jìn)入binder_ioctl后, binder_thread->looper已經(jīng)沒有了BINDER_LOOPER_STATE_NEED_RETURN
所以binder_has_proc_work就會(huì)返回false, 然后binder線程就這樣一直阻塞式的阻塞了。
整個(gè)過程如下

四、Server端的binder線程是怎么被喚醒的呢?
由第三節(jié)知道 Server端的binder線程一直阻塞在 binder_thread_read 這個(gè)函數(shù)的中的, 也就是
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
注意wait_event_freezable_exclusive是一個(gè)排他的等待隊(duì)列,當(dāng)喚醒該等待隊(duì)列時(shí),只會(huì)喚醒第一個(gè)。
對應(yīng)的binder線程要被喚醒,那么就找下哪里 wake up了 proc->wait就知道了。
下面來看幾種正常的情況
4.1 被其它進(jìn)程(binder_proc)喚醒
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
{
...
if (target_thread) { //一般這里為false
e->to_thread = target_thread->pid;
target_list = &target_thread->todo;
target_wait = &target_thread->wait;
} else { //取得的是進(jìn)程上的todo等待列表
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
}
...
list_add_tail(&t->work.entry, target_list);
if (target_wait) //喚醒
wake_up_interruptible(target_wait);
...
}
當(dāng)client進(jìn)程需要獲得server端的服務(wù)時(shí),如調(diào)用一個(gè)"server端的API函數(shù)", 最終binder驅(qū)動(dòng)會(huì)找到server的binder_proc,也就是代碼中的target_proc, 接著client將要請求server的相關(guān)數(shù)據(jù)加入到server的等待隊(duì)列中,也就是target_list, 最后通過wake_up_interruptible喚醒server線程來處理client的請求。

注意,這里只會(huì)喚醒一個(gè)binder線程(因?yàn)樗邥r(shí)是wait_event_freezable_exclusive)
4.2 被自己喚醒
4.1節(jié)會(huì)喚醒一個(gè)binder線程去執(zhí)行客戶端的請求,來看下server端客戶線程會(huì)喚醒后做了什么操作
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg, struct binder_thread *thread)
{
...
if (bwr.write_size > 0) {
...
}
if (bwr.read_size > 0) {
ret = binder_thread_read(proc, thread, bwr.read_buffer,
bwr.read_size,&bwr.read_consumed,filp->f_flags & O_NONBLOCK);
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
}
...
}
當(dāng)server有一個(gè)binder線程被喚醒了,這時(shí)binder線程就會(huì)返回到用戶態(tài)去執(zhí)行相關(guān)操作,在返回之前, binder線程又會(huì)檢查是否現(xiàn)在binder驅(qū)動(dòng)比較繁忙,也就是是否還有其它的客戶端請求,如果還有,那么當(dāng)前binder線程觸發(fā)喚醒server進(jìn)程上的等待的其它binder線程。
也就是說,當(dāng)有binder線程被喚醒時(shí),binder線程就可能會(huì)喚醒其它的binder線程盡量將當(dāng)前等待著的請求執(zhí)行完。
4.3 binder死亡通知
如linkToDeath, 這里不討論這種情況。
五、client是怎么找到server端在binder驅(qū)動(dòng)中的binder_proc的呢?
在4.1節(jié)binder_transaction,client通過找到target_proc,然后就喚醒了server端的binder線程,那么這個(gè)target_proc是怎么來的呢?
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
{
struct binder_proc *target_proc;
if (reply) { //reply在 BC_TRANACTION時(shí)為false
} else { //進(jìn)入else分支
if (tr->target.handle) { //如果handle不為0,則進(jìn)入下面的分支
struct binder_ref *ref;
ref = binder_get_ref(proc, tr->target.handle, true);
//通過handle在當(dāng)前binder_proc中獲得target的binder_ref, 也就是binder_node的引用
target_node = ref->node; //通過引用獲得target binder node
} else { //如果handle為0的話進(jìn)入else分支
target_node = binder_context_mgr_node; //這個(gè)是固定的ServiceManager
}
target_proc = target_node->proc;
}
if (target_thread) {
} else {
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
}
...
}
哦,原來是通過 handle 這個(gè)整形數(shù)來獲得的target binder proc. 那這個(gè)handle又是什么呢? 從上面看出是binder_transaction_data里面的handle,

而整個(gè)transact傳遞流程如下

從代碼上來看
status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
這個(gè)handle是BpBinder里的mHandle,
那么問題來了,BpBinder里的mHandle又是怎么初始化的呢