FregClient和FregServer进程间通信

本文参考《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

时间: 2024-10-25 12:05:14

FregClient和FregServer进程间通信的相关文章

Andorid Binder进程间通信---Java接口源代码--System和应用程序进程间通信

本文参考<Android系统源代码情景分析>,作者罗升阳 一.架构代码: ~/Android/frameworks/base/core/java/android/os ----IInterface.java (Interface) ----IServiceManager.java (IServiceManager) ----IBinder.java (IBinder) ----Binder.java (BinderProxy,Binder) ----ServiceManagerNative.j

Android Binder进程间通信---ServiceManager代理对象的获取过程

本文参考<Android系统源代码情景分析>,作者罗升阳. 一.测试代码: -/Android/external/binder/server ----FregServer.cpp ~/Android/external/binder/common ----IFregService.cpp ----IFregService.h ~/Android/external/binder/client ----FregClient.cpp Binder库(libbinder)代码: ~/Android/fr

Android Binder进程间通信---注册Service组件---发送和处理BC_REPLY返回协议

本文参考<Android系统源代码情景分析>,作者罗升阳 一.测试代码: -/Android/external/binder/server ----FregServer.cpp ~/Android/external/binder/common ----IFregService.cpp ----IFregService.h ~/Android/external/binder/client ----FregClient.cpp Binder库(libbinder)代码: ~/Android/fra

Android Binder进程间通信---注册Service组件---封装进程间通信数据

本文参考<Android系统源代码情景分析>,作者罗升阳 一.测试代码: -/Android/external/binder/server ----FregServer.cpp ~/Android/external/binder/common ----IFregService.cpp ----IFregService.h ~/Android/external/binder/client ----FregClient.cpp Binder库(libbinder)代码: ~/Android/fra

Android Binder进程间通信---注册Service组件---发送和处理BC_TRANSACTION

本文参考<Android系统源代码情景分析>,作者罗升阳 一.测试代码: -/Android/external/binder/server ----FregServer.cpp ~/Android/external/binder/common ----IFregService.cpp ----IFregService.h ~/Android/external/binder/client ----FregClient.cpp Binder库(libbinder)代码: ~/Android/fra

Android Binder进程间通信---注册Service组件---启动Binder线程池

本文参考<Android系统源代码情景分析>,作者罗升阳 一.测试代码: -/Android/external/binder/server ----FregServer.cpp ~/Android/external/binder/common ----IFregService.cpp ----IFregService.h ~/Android/external/binder/client ----FregClient.cpp Binder库(libbinder)代码: ~/Android/fra

Android Binder进程间通信---Service代理对象的获取过程

本文参考<Android系统源代码情景分析>,作者罗升阳 一.测试代码: -/Android/external/binder/server ----FregServer.cpp ~/Android/external/binder/common ----IFregService.cpp ----IFregService.h ~/Android/external/binder/client ----FregClient.cpp Binder库(libbinder)代码: ~/Android/fra

Linux进程间通信总结

Linux进程间通信总结 1. 管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: (1)管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: (2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): (3)单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. (4)数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出

Xenomai 进程间通信方式

Xenomai 进程间通信方式分成Xenomai域内的IPC以及Xenomai域和Linux域之间的IPC, 目前采用的rtipc(RTDM驱动)的方式,主要是给用户空间提供socket接口,实时应用 通过调用对应的接口可以避免切换到Linux域而导致实时性降低.rtipc对应了三个协议: XDDP (Xenomai域和Linux域之间的IPC) IDDP和BUFP (Xenomai域内的IPC) 另外,原有的RT_PIPE机制仍旧支持,但从Xenomai 3开始就不支持了. http://ww