本文参考《Android系统源代码情景分析》,作者罗升阳
一、测试代码:
~/Android/external/binder/server
----FregServer.cpp
~/Android/external/binder/common
----IFregService.cpp
----IFregService.h
~/Android/external/binder/client
----FregClient.cpp
Binder库(libbinder)代码:
~/Android/frameworks/base/libs/binder
----BpBinder.cpp
----Parcel.cpp
----ProcessState.cpp
----Binder.cpp
----IInterface.cpp
----IPCThreadState.cpp
----IServiceManager.cpp
----Static.cpp
~/Android/frameworks/base/include/binder
----Binder.h
----BpBinder.h
----IInterface.h
----IPCThreadState.h
----IServiceManager.h
----IBinder.h
----Parcel.h
----ProcessState.h
驱动层代码:
~/Android//kernel/goldfish/drivers/staging/android
----binder.c
----binder.h
二、源码分析
1、FregClient进程,获取BpFregService类型代理对象。参考FregClient进程,创建一个BpFregService类型的代理对象一文http://blog.csdn.net/jltxgcy/article/details/26370733。
~/Android/external/binder/client
----FregClient.cpp
int main() { sp<IBinder> binder = defaultServiceManager()->getService(String16(FREG_SERVICE));//获取了FregClient进程的代理对象 if(binder == NULL) { LOGE("Failed to get freg service: %s.\n", FREG_SERVICE); return -1; } sp<IFregService> service = IFregService::asInterface(binder);//获取BpFregService类型的代理对象 if(service == NULL) { LOGE("Failed to get freg service interface.\n"); return -2; } printf("Read original value from FregService:\n"); int32_t val = service->getVal();//会调用BpFregService的getVal方法 printf(" %d.\n", val); printf("Add value 1 to FregService.\n"); val += 1; service->setVal(val); printf("Read the value from FregService again:\n"); val = service->getVal(); printf(" %d.\n", val); return 0; }
2、FregClient进程,封装进程间通信数据。参考FregServer进程,封装进程间通信数据http://blog.csdn.net/jltxgcy/article/details/26059215。
此时没有对象要传递,只有字符串。
执行到service->getVal(),会调用BpFregService的getVal方法。实现如下:
~/Android/external/binder/common
----IFregService.cpp
int32_t getVal() { Parcel data; data.writeInterfaceToken(IFregService::getInterfaceDescriptor());//shy.luo.FregService,封装进程间通信数据 Parcel reply; remote()->transact(GET_VAL, data, &reply);//刚刚获取的FregClient进程代理对象 int32_t val = reply.readInt32();//0 return val; }
3、FregClient进程,发送BC_TRANSACTION,睡眠等待。参考FregServer进程,发送BC_TRANSACTION,睡眠等待http://blog.csdn.net/jltxgcy/article/details/26076149。
执行到binder_transaction,会有些不同。binder_get_ref获得FregClient进程的引用对象,并且找到目标进程也就是FregServer进程。
4、FregServer进程,处理BC_TRANSACTION,返回BR_TRANSACTION。
(1)、参考Service Manager进程,处理BC_TRANSACTION,返回BR_TRANSACTIONhttp://blog.csdn.net/jltxgcy/article/details/26151113。
tr.target.ptr为FregServer进程的本地对象的弱引用计数的地址,tr.cookie为FregServer进程的本地对象地址。thread->transaction_stack = t;
(2)、参考FregServer进程,启动Binder线程池http://blog.csdn.net/jltxgcy/article/details/26354311。
FregServer进程执行完talkWithDriver后,mIn中存放了BR_TRANSACTION命令和传递过来的binder_transaction_data结构体。
继续执行executeCommand实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
status_t IPCThreadState::executeCommand(int32_t cmd) { BBinder* obj; RefBase::weakref_type* refs; status_t result = NO_ERROR; switch (cmd) {//BR_TRANSACTION ...... case BR_TRANSACTION: { binder_transaction_data tr; result = mIn.read(&tr, sizeof(tr));//读取出传递过来的binder_transaction_data结构体 ...... if (result != NO_ERROR) break; Parcel buffer;//把数据放入buffer中 buffer.ipcSetDataReference( reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(size_t), freeBuffer, this); ..... Parcel reply; ..... if (tr.target.ptr) {//FregServer进程的本地对象的弱引用计数的地址 sp<BBinder> b((BBinder*)tr.cookie);//tr.cookie原来为IBinder向下转型为BBinder const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);//code为GET_VAL if (error < NO_ERROR) reply.setError(error); } else { ...... } ....... if ((tr.flags & TF_ONE_WAY) == 0) { ....... sendReply(reply, 0); } else { ...... } ...... } break; ...... return result; }
首先,读取出传递过来的binder_transaction_data结构体,并把其中的数据放入buffer中,调用BBinder的transact方法,实现如下:
~/Android/frameworks/base/libs/binder
----Binder.cpp
status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { data.setDataPosition(0); status_t err = NO_ERROR; switch (code) { case PING_TRANSACTION: reply->writeInt32(pingBinder()); break; default: err = onTransact(code, data, reply, flags);//code为GET_VAL break; } if (reply != NULL) { reply->setDataPosition(0); } return err; }
BBinder的onTransact方法,由于子类BnFregService复写了onTransact方法,所以调用该方法。实现如下:
~/Android/external/binder/common
----IFregService.cpp
status_t BnFregService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code)//GET_VAL { case GET_VAL: { CHECK_INTERFACE(IFregService, data, reply); int32_t val = getVal();//目前返回0 reply->writeInt32(val);//返回中写入0 return NO_ERROR; } case SET_VAL: { CHECK_INTERFACE(IFregService, data, reply); int32_t val = data.readInt32(); setVal(val); return NO_ERROR; } default: { return BBinder::onTransact(code, data, reply, flags); } } }
其中CHECK_INTERFACE实现如下:
~/Android/frameworks/base/include/binder
----IInterface.h
#define CHECK_INTERFACE(interface, data, reply) if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \
~/Android/frameworks/base/libs/binder
----Parcel.cpp
bool Parcel::checkInterface(IBinder* binder) const { return enforceInterface(binder->getInterfaceDescriptor()); }
由于子类BnInterface复写了getInterfaceDescriptor方法,所以实现如下:
~/Android/frameworks/base/include/binder
----IInterface.h
inline const String16& BnInterface<IFregService>::getInterfaceDescriptor() const { return IFregService::getInterfaceDescriptor();//shy.luo.FregService }
enforceInterface函数实现如下:
~/Android/frameworks/base/libs/binder
----Parcel.cpp
bool Parcel::enforceInterface(const String16& interface, IPCThreadState* threadState) const { int32_t strictPolicy = readInt32(); if (threadState == NULL) { threadState = IPCThreadState::self(); } ...... const String16 str(readString16());//str为shy.luo.FregService if (str == interface) {//interface也为shy.luo.FregService return true; } else { ....... return false; } }
返回onTransact函数,继续执行getVal,调用IFregService的方法getVal,由于是纯虚函数,所以最终会执行FregServer的getVal方法,实现如下:
~/Android/external/binder/server
----FregServer.cpp
int32_t getVal() { int32_t val = 0; if(fd != -1) { read(fd, &val, sizeof(val));//读的是/dev/freg } return val; }
5、FregServer进程,发送BC_REPLY,睡眠等待。
程序逐层返回,最终返回到executeCommand函数,继续执行函数sendReply,实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)//flags为0 { status_t err; status_t statusBuffer; err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer); if (err < NO_ERROR) return err; return waitForResponse(NULL, NULL); }
writeTransactionData函数实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)//data就是reply,目前保存是返回值0 { binder_transaction_data tr; tr.target.handle = handle;//-1 tr.code = code;//0 tr.flags = binderFlags;//0 const status_t err = data.errorCheck(); if (err == NO_ERROR) { tr.data_size = data.ipcDataSize();//数据缓冲区大小 tr.data.ptr.buffer = data.ipcData();//数据缓冲区的起始位置 tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);//偏移数组大小 tr.data.ptr.offsets = data.ipcObjects();//偏移数组起始位置 } else if (statusBuffer) { ........ } else { ........ } mOut.writeInt32(cmd);//BC_REPLY mOut.write(&tr, sizeof(tr)); return NO_ERROR; }
waitForResponse函数实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { int32_t cmd; int32_t err; while (1) { if ((err=talkWithDriver()) < NO_ERROR) break; err = mIn.errorCheck(); if (err < NO_ERROR) break; if (mIn.dataAvail() == 0) continue; cmd = mIn.readInt32();//读取了BR_TRANSACTION_COMPLETE协议,mIn中就没有数据了 ..... switch (cmd) { case BR_TRANSACTION_COMPLETE: if (!reply && !acquireResult) goto finish;//reply不为NULL break; ..... } ........ return err; }
talkWithDriver最终会执行binder_thread_write和binder_thread_read,请参考Service Manager进程,发送BC_REPLY,睡眠等待http://blog.csdn.net/jltxgcy/article/details/26216521。执行完binder_thread_read返回到waitForResponse,读出命令为BR_TRANSACTION_COMPLETE,由于reply为NULL,go
finish,那么该函数执行完毕。
然后返回sendReply,再返回executeCommand,最后返回joinThreadPool。joinThreadPool又调用了talkWithDriver,调用binder_thread_read函数。睡眠等待。
6、FregClient进程,处理BC_REPLY,返回BR_REPLY。参考FregServer进程,处理BC_REPLY,返回BR_REPLYhttp://blog.csdn.net/jltxgcy/article/details/26339313
7、FregClient进程,返回到BpFregService的getVal方法。
reply.readInt32()等于0,终于得到结果了。TMD。
最后返回FregClient的main函数,打印出结果。
至此整个一次进程间通信,结束了。
FregServer进程和Service Manager进程间通信;
FregClient进程和Service Manager进程间通信;
FregServer进程和 FregClient进程间通信。
FregServer进程一致在等待请求。
FregClient发送请求。
FregClient和FregServer进程间通信,布布扣,bubuko.com