Android Binder 修炼之道(四)Binder 系统C++ 发送数据过程以及Server注册服务处理数据的过程

来源:互联网 发布:java 查看线程状态 编辑:程序博客网 时间:2024/06/04 19:13
本节分析发送数据过程以及Server注册服务处理数据的过程
经过前面的学习,我们知道 service 其实是一个 BpCalculateService 代理类对象的指针,因此:
1
    int reduceone(int n)
2
    {
3
        /* 构造/发送数据 */
4
        Parcel data, reply;
5
6
        data.writeInt32(0);
7
        data.writeInt32(n);
8
9
10
        remote()->transact(SVR_CMD_REDUCE_ONE, data, &reply);
11
12
        return reply.readInt32();
13
    }


remote 函数是在 BpXXXService 的父类 BpRefBase 中实现的
前面一节分析过,这里的 mRemote 指向一个 BpBinder 对象,这个 BpBinder 对象是通过一个 handle 构造而来,这个 handle 也就是对应的服务的 handle 
1
status_t BpBinder::transact(
2
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3
{
4
    // Once a binder has died, it will never come back to life.
5
    if (mAlive) {
6
        status_t status = IPCThreadState::self()->transact(
7
            mHandle, code, data, reply, flags);
8
        if (status == DEAD_OBJECT) mAlive = 0;
9
        return status;
10
    }
11
12
    return DEAD_OBJECT;
13
}
1
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
2
{
3
    int32_t cmd;
4
    int32_t err;
5
6
    while (1) {
7
        if ((err=talkWithDriver()) < NO_ERROR) break;
8
        ...
9
    }
10
}
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr
回归到C语言了,IPCThreadState::mProcess->mDriverFD 这个就是 Binder 驱动的文件句柄,还得看看它是哪里来的。

Client 程序的刚开始有这么一句:
1
/* 打开驱动, mmap */
2
    sp<ProcessState> proc(ProcessState::self());

1
ProcessState::ProcessState()
2
    : mDriverFD(open_driver())
3
    , mVMStart(MAP_FAILED)
4
    , mManagesContexts(false)
5
    , mBinderContextCheckFunc(NULL)
6
    , mBinderContextUserData(NULL)
7
    , mThreadPoolStarted(false)
8
    , mThreadPoolSeq(1)
9
{
10
    if (mDriverFD >= 0) {
11
        // XXX Ideally, there should be a specific define for whether we
12
        // have mmap (or whether we could possibly have the kernel module
13
        // availabla).
14
#if !defined(HAVE_WIN32_IPC)
15
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
16
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
17
        if (mVMStart == MAP_FAILED) {
18
            // *sigh*
19
            ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
20
            close(mDriverFD);
21
            mDriverFD = -1;
22
        }
23
#else
24
        mDriverFD = -1;
25
#endif
26
    }
27
28
    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
29
}
mDriverFD(open_driver() 
mDriverFD = open("/dev/binder", O_RDWR);

是时候分析 Server 这边的工作了:
1
int main(void)
2
{
3
    /* addService */
4
5
    /* while(1){ read data, 解析数据, 调用服务函数 } */
6
7
    /* 打开驱动, mmap */
8
    sp<ProcessState> proc(ProcessState::self());
9
10
    /* 获得BpServiceManager */
11
    sp<IServiceManager> sm = defaultServiceManager();
12
13
    sm->addService(String16("calculate"), new BnCalculateService());
14
15
    /* 循环体 */
16
    ProcessState::self()->startThreadPool();
17
    IPCThreadState::self()->joinThreadPool();
18
19
    return 0;
20
}
首先是 addService 的过程,sm 实际上是 BpServiceManager 因此:
data.writeStrongBinder(service);  // service = new BnHelloService();
    flatten_binder(ProcessState::self(), val, this); // val = service = new BnHelloService();
        flat_binder_object obj;         // 参数 binder = val = service = new BnHelloService();
        IBinder *local = binder->localBinder();     // =this = new BnHelloService();
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
        obj.cookie = reinterpret_cast<uintptr_t>(local);  // new BnHelloService();
将 BnHelloService 的指针付给了 obj.cookie
这里也是 remote->transact 所以没啥好分析的了和 Client 发送数据是一样的,那么看看 Server 收到数据是如何处理的

1
void IPCThreadState::joinThreadPool(bool isMain)
2
{
3
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
4
5
    set_sched_policy(mMyThreadId, SP_FOREGROUND);
6
        
7
    status_t result;
8
    do {
9
        processPendingDerefs();
10
        
11
        // now get the next command to be processed, waiting if necessary
12
        result = getAndExecuteCommand();
13
14
    } while (result != -ECONNREFUSED && result != -EBADF);
15
    
16
    mOut.writeInt32(BC_EXIT_LOOPER);
17
    talkWithDriver(false);
18
}
sp<BBinder> b((BBinder*)tr.cookie);
                error = b->transact(tr.code, buffer, &reply, tr.flags);
b 就指向了 BnHelloService
1
status_t BBinder::transact(
2
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3
{
4
    data.setDataPosition(0);
5
6
    status_t err = NO_ERROR;
7
    switch (code) {
8
        case PING_TRANSACTION:
9
            reply->writeInt32(pingBinder());
10
            break;
11
        default:
12
            err = onTransact(code, data, reply, flags);
13
            break;
14
    }
15
16
    if (reply != NULL) {
17
        reply->setDataPosition(0);
18
    }
19
20
    return err;
21
}
这里就调用到了,BnHelloService->onTransact 函数

总结:
    1、发送数据都用 remote()->transact ,利用 ProcessState 里的 binder fd 通过 ioctl 发送数据
    2、注册服务的实质,将一个BnXXXService的指针,作为flat_binder_object.cookie 注册进去
    3、Service 处理数据实质,取出 cookie 也就是 BnXXXService 调用它的 onTransact 函数
阅读全文
1 0
原创粉丝点击