本文参考《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
二、源码分析
上一篇文章Android Binder进程间通信---注册Service组件---封装进程间通信数据http://blog.csdn.net/jltxgcy/article/details/26059215,我们执行完了addService中封装数据部分代码,如下:
~/Android/frameworks/base/libs/binder
----IServiceManager.cpp
class BpServiceManager : public BpInterface<IServiceManager> { public: ......... virtual status_t addService(const String16& name, const sp<IBinder>& service) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//写入一个Binder进程间通信请求头 data.writeString16(name);//写入将要注册的Service组件的名称 data.writeStrongBinder(service);//将要注册的Service组件封装成一个flat_binder_object结构体,写入data status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);//remote为BpBinder对象 return err == NO_ERROR ? reply.readExceptionCode() : err; } .......... };
接下来调用内部的一个Binder代理对象的成员函数transact发送一个ADD_SERVICE_TRANSACTION命令协议。
remote()获取BpBinder对象,调用它的成员函数transact函数,实现如下:
~/Android/frameworks/base/libs/binder
----BpBinder.cpp
status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)//注意data是一个引用,reply是一个指针 { // 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; }
目前mHandle为0,code为ADD_SERVICE_TRANSACTION,data包含了要传递给Binder驱动程序的进程间通信数据;第三个参数reply是一个输出参数,用来保存进程间通信结果,第四个参数flags用来描述这是一个同步的进程间通信请求,还是一个异步的进程间通信请求,它是一个默认参数,默认值为0,表示这是一个同步的进程请求。
调用上文http://blog.csdn.net/jltxgcy/article/details/25953361已经创建的IPCThreadState对象的成员函数transact,实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t err = data.errorCheck(); flags |= TF_ACCEPT_FDS;//flags等于0|TF_ACCEPT_FDS ....... if (err == NO_ERROR) { .......... err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);//将data的内容写入到一个binder_transaction_data结构体中 } ........ if ((flags & TF_ONE_WAY) == 0) {//最后一位为0,按位与TF_ONE_WAY等于0,表示同步的进程间通信请求 .......... if (reply) {//reply不为空,是一个指针 err = waitForResponse(reply); } else { ......... } .......... } else { .......... } return err; }
其中, TF_ACCEPT_FDS,TF_ONE_WAY定义在一个枚举中。实现如下:
~/Android/frameworks/base/include/binder
----binder.h
enum transaction_flags { TF_ONE_WAY = 0x01, TF_ROOT_OBJECT = 0x04, TF_STATUS_CODE = 0x08, TF_ACCEPT_FDS = 0x10, };
首先检查Parcel对象中的进程间通信数据是否正确,然后将参数flags的TF_ACCEPT_FDS位设置为1,表示允许Server进程在返回结果中携带文件描述符。如果Parcel对象data中的进程间通信数据没有问题,那么就会调用成员函数writeTransactionData将它的内容写入到一个binder_transaction_data结构体中。接着判断flags的TF_ONE_WAY位是否等于0。如果是,那么就说明这是一个同步的进程间通信请求,这时候如果用来保存通信结果的Parcel对象reply不等于NULL,那么就调用成员函数waitForResponse函数。
我们先来分析writeTransactionData函数,实现如下:
~/Android/frameworks/base/include/binder
----IPCThreadState.cpp
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,//此时cmd为BC_TRANSACTION,binderFlags为0|TF_ACCEPT_FDS int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)//handle为0,code为ADD_SERVICE_TRANSACTION,data包含了包含了要传递给Binder驱动程序的进程间通信数据,statusBuffer为NULL { binder_transaction_data tr; tr.target.handle = handle;//0 tr.code = code;//ADD_SERVICE_TRANSACTION tr.flags = binderFlags;//0|TF_ACCEPT_FDS 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_TRANSACTION mOut.write(&tr, sizeof(tr)); return NO_ERROR; }
其中binder_transaction_data结构体,实现如下:
struct binder_transaction_data { union { size_t handle; void *ptr; } target; void *cookie; unsigned int code; unsigned int flags; pid_t sender_pid; uid_t sender_euid; size_t data_size; size_t offsets_size; union { struct { const void *buffer; const void *offsets; }ptr; uint8_t buf[8]; } data; };
执行完writeTransactionData,此时命令协议缓冲区mOut的内存布局如下图:
注意此图有错误,flat_binder_object中cookie为BBinder类指针,即binder本地对象指针。binder为本地对象弱引用计数的地址。
执行完writeTransactionData函数,该执行waitForResponse函数了,实现如下:
~/Android/frameworks/base/include/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; ..... } ....... }
这个函数通过一个while循环不断地调用成员函数talkWithDriver来与Binder驱动程序进行交互,以便可以将前面准备好的BC_TRANSACTION命令协议发送给Binder驱动程序处理,并等待Binder驱动程序将进程间通信结果返回来。
talkWithDriver函数实现如下:
~/Android/frameworks/base/include/binder
----IPCThreadState.cpp
status_t IPCThreadState::talkWithDriver(bool doReceive) { LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened"); binder_write_read bwr; // Is the read buffer empty? const bool needRead = mIn.dataPosition() >= mIn.dataSize();//needRead为1,表示有需要读的数据 // 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;//doReceive为true表示,只接受Binder驱动程序发送给该进程的返回协议。默认为true。doReceive为false,即不只接受Binder驱动程序发送给该进程的返回协议,或者有需要读的数据,那么outAvail就不为0 bwr.write_size = outAvail;//要写入的数据大小 bwr.write_buffer = (long unsigned int)mOut.data();//要写入的数据起始位置 // This is what we‘ll read. if (doReceive && needRead) { bwr.read_size = mIn.dataCapacity();//读入数据的大小 bwr.read_buffer = (long unsigned int)mIn.data();//读入数据的起始位置 } else { bwr.read_size = 0; } ......... // Return immediately if there is nothing to do. if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;//如果两者都为0,就不用继续执行驱动程序了 bwr.write_consumed = 0;//消费清0 bwr.read_consumed = 0;//消费清0 status_t err; do { ......... #if defined(HAVE_ANDROID_OS) if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)//IPCThreadState在构造函数初始化时,初始化了mProcess err = NO_ERROR; else err = -errno; #else err = INVALID_OPERATION; #endif IF_LOG_COMMANDS() { alog << "Finished read/write, write size = " << mOut.dataSize() << endl; } } while (err == -EINTR); ........ if (err >= NO_ERROR) { if (bwr.write_consumed > 0) { if (bwr.write_consumed < (ssize_t)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; }
在IPCThreadState类内部,除了使用缓冲区mOut来保存即将要发送给Binder驱动程序的命令协议外,还使用缓冲区mIn来保存那些从Binder驱动程序接受到的返回协议。
通过IPCThreadState类的mIn,mOut设置一个局部变量binder_write_read结构体,最后调用了ioctl映射到Binder驱动程序去执行。
~/Android/kernel/goldfish/drivers/staging/android
----binder.c
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; struct binder_proc *proc = filp->private_data; struct binder_thread *thread; unsigned int size = _IOC_SIZE(cmd); void __user *ubuf = (void __user *)arg;//上面传递的过来的局部变量binder_write_read结构体的地址 ......... mutex_lock(&binder_lock); thread = binder_get_thread(proc);//第一次获取的thread,looper为BINDER_LOOPER_STATE_NEED_RETURN if (thread == NULL) { ret = -ENOMEM; goto err; } switch (cmd) {//cmd为上面传递过来的BINDER_WRITE_READ case BINDER_WRITE_READ: { struct binder_write_read bwr; if (size != sizeof(struct binder_write_read)) { ret = -EINVAL; goto err; } if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {//从用户空间传进来的一个binder_write_read结构体拷贝出来,并且保存在变量bwr中,里面有数据地址,数据总大小,数据现在消费了多少 ret = -EFAULT; goto err; } ......... if (bwr.write_size > 0) {//bwr.write_size大于0,执行这里 ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); if (ret < 0) { bwr.read_consumed = 0; if (copy_to_user(ubuf, &bwr, sizeof(bwr))) ret = -EFAULT; goto err; } } if (bwr.read_size > 0) {//bwr.read_size大于0,执行这里 ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); if (!list_empty(&proc->todo)) wake_up_interruptible(&proc->wait); if (ret < 0) { if (copy_to_user(ubuf, &bwr, sizeof(bwr))) ret = -EFAULT; goto err; } } ........... if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {//将结果返回用户空间bwr ret = -EFAULT; goto err; } break; } .......... ret = 0; err: if (thread) thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; mutex_unlock(&binder_lock); ........... return ret; }
Android Binder进程间通信---注册Service组件---发送和处理BC_TRANSACTION