FregClient和FregServer进程间通信

来源:互联网 发布:高分一号卫星数据下载 编辑:程序博客网 时间:2024/04/30 10:57

本文参考《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();//0return val;}
      

        3、FregClient进程,发送BC_TRANSACTION,唤醒FregServer进程,返回BR_TRANSACTION_COMPLETE,睡眠等待主线程thread->wait。

      参考FregServer进程,发送BC_TRANSACTION,唤醒ServiceManager进程,返回BR_TRANSACTION_COMPLETE,睡眠等待主线程thread->wait,http://blog.csdn.net/jltxgcy/article/details/26076149

       执行到binder_transaction,会有些不同。binder_get_ref获得FregClient进程的引用对象,并且找到目标进程也就是FregServer进程。thread->transaction_stack = t,FregClient的主线程。

 if (reply) {//为0          .........      } else {          if (tr->target.handle) {//不为0              struct binder_ref *ref;              ref = binder_get_ref(proc, tr->target.handle); //获得了FregClient进程的引用对象(引用了FregServer进程的实体对象)             .......              target_node = ref->node;//FregServer进程的实体对象          } else {              target_node = binder_context_mgr_node;            ........          }          ........          target_proc = target_node->proc;//找到了目标FregServer进程          ........          if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {//目前thread->transaction_stack为NULL,所以暂时不执行这里              struct binder_transaction *tmp;              tmp = thread->transaction_stack;              ........              while (tmp) {                  if (tmp->from && tmp->from->proc == target_proc)                      target_thread = tmp->from;                  tmp = tmp->from_parent;              }          }      }  

       4、FregServer进程从睡眠中被唤醒,返回BR_TRANSACTION,执行真正意义的getVal。

       (1)、参考Service Manager进程从睡眠中被唤醒,返回BR_TRANSACTION,执行真正意义的addService,http://blog.csdn.net/jltxgcy/article/details/26151113。

        参考这里的binder_thread_read,tr.target.ptr为FregServer进程的本地对象的弱引用计数的地址,tr.cookie为FregServer进程的本地对象地址。thread->transaction_stack = t;FregServer的主线程或者另一个线程,看哪个线程先读取数据。另一线程继续睡眠等待

      不同之处:

if (t->buffer->target_node) {              struct binder_node *target_node = t->buffer->target_node;              tr.target.ptr = target_node->ptr;//Binder实体对象ptr为FregServer进程的本地对象的弱引用计数的地址            tr.cookie =  target_node->cookie;//Binder实体对象cookie为FregServer进程的本地对象地址              t->saved_priority = task_nice(current);              if (t->priority < target_node->min_priority &&                  !(t->flags & TF_ONE_WAY))                  binder_set_nice(t->priority);              else if (!(t->flags & TF_ONE_WAY) ||                   t->saved_priority > target_node->min_priority)                  binder_set_nice(target_node->min_priority);              cmd = BR_TRANSACTION;//cmd设置BR_TRANSACTION          }

       (2)、参考FregServer进程,启动Binder线程池http://blog.csdn.net/jltxgcy/article/details/26354311。
       FregServer进程从binder_thread_read返回到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结构体,tr中实际的数据只有shy.luo.FregService            ......            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,buffer里面是shy.luo.FregService                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,唤醒FregClient进程,返回BR_TRANSACTION_COMPLETE,睡眠等待在proc->wait

       程序逐层返回,最终返回到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,binder_thread_write把FregServer和FregClient的thread->transaction_stack都赋值为NULL

       binder_thread_write,请参考Service Manager进程,发送BC_REPLY,唤醒FregServer进程,返回BR_TRANSACTION_COMPLETE,睡眠等待在proc->wait,http://blog.csdn.net/jltxgcy/article/details/26216521。

       talkWithDriver,请参考http://blog.csdn.net/jltxgcy/article/details/26076149。

       执行完binder_thread_read返回到waitForResponse,读出命令为BR_TRANSACTION_COMPLETE,由于reply为NULL,go finish,那么该函数执行完毕,也参考http://blog.csdn.net/jltxgcy/article/details/26216521。

       然后返回sendReply,再返回executeCommand,最后返回joinThreadPool。joinThreadPool又调用了talkWithDriver,调用binder_thread_read函数。由于FregServer的thread->transaction_stack都赋值为NULL,睡眠等待在proc->wait,此时ready_thread还为2个。


       6、FregClient进程,返回BR_REPLY。参考FregServer进程,返回BR_REPLY,http://blog.csdn.net/jltxgcy/article/details/26339313

       7、FregClient进程,层层返回到BpFregService的getVal方法。

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();//0return val;}

       最后返回FregClient的main函数,打印出结果。


    

       至此整个一次进程间通信,结束了。

       FregServer进程和Service Manager进程间通信;

       FregClient进程和Service Manager进程间通信;

       FregServer进程和 FregClient进程间通信。

       FregServer进程一致在等待请求。

       FregClient发送请求。

0 0
原创粉丝点击