Binder系列---服务添加过程(4)

55 阅读3分钟

do_add_service

int do_add_service(struct binder_state *bs,
                   const uint16_t *s, size_t len,
                   uint32_t handle, uid_t uid, int allow_isolated,
                   pid_t spid)
{
    struct svcinfo *si;
    //服务检索
    si = find_svc(s, len);
    if (si) {
        if (si->handle) {
            svcinfo_death(bs, si); //服务已注册时,释放相应的服务
        }
        si->handle = handle;
    } else {
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {  //内存不足,无法分配足够内存
            return -1;
        }
        si->handle = handle;
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); //内存拷贝服务信息
        si->next = svclist; // svclist保存所有已注册的服务
        svclist = si;
    }

    //以BC_ACQUIRE命令,handle为目标的信息,通过ioctl发送给binder驱动
    binder_acquire(bs, handle);
    //以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通过ioctl发送给binder驱动,主要用于清理内存等收尾工作。
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}

svcinfo记录着服务名和handle信息,保存到svclist列表。

五. 总结

服务注册过程(addService)核心功能:在服务所在进程创建binder_node,在servicemanager进程创建binder_ref。 其中binder_ref的desc再同一个进程内是唯一的:

  • 每个进程binder_proc所记录的binder_ref的handle值是从1开始递增的;
  • 所有进程binder_proc所记录的handle=0的binder_ref都指向service manager;
  • 同一个服务的binder_node在不同进程的binder_ref的handle值可以不同;

Media服务注册的过程涉及到MediaPlayerService(作为Client进程)和Service Manager(作为Service进程),通信流程图如下所示: image.png

过程分析:

  1. MediaPlayerService进程调用ioctl()向Binder驱动发送IPC数据,该过程可以理解成一个事务binder_transaction(记为T1),执行当前操作的线程binder_thread(记为thread1),则T1->from_parent=NULL,T1->from = thread1,thread1->transaction_stack=T1。其中IPC数据内容包含:

    • Binder协议为BC_TRANSACTION;
    • Handle等于0;
    • RPC代码为ADD_SERVICE;
    • RPC数据为”media.player”。
  2. Binder驱动收到该Binder请求,生成BR_TRANSACTION命令,选择目标处理该请求的线程,即ServiceManager的binder线程(记为thread2),则 T1->to_parent = NULL,T1->to_thread = thread2。并将整个binder_transaction数据(记为T2)插入到目标线程的todo队列;

  3. Service Manager的线程thread2收到T2后,调用服务注册函数将服务”media.player”注册到服务目录中。当服务注册完成后,生成IPC应答数据(BC_REPLY),T2->form_parent = T1,T2->from = thread2, thread2->transaction_stack = T2。

  4. Binder驱动收到该Binder应答请求,生成BR_REPLY命令,T2->to_parent = T1,T2->to_thread = thread1, thread1->transaction_stack = T2。 在MediaPlayerService收到该命令后,知道服务注册完成便可以正常使用。

整个过程中,BC_TRANSACTION和BR_TRANSACTION过程是一个完整的事务过程;BC_REPLY和BR_REPLY是一个完整的事务过程。 到此,其他进行便可以获取该服务,使用服务提供的方法。

# Binder系列---服务添加过程(1)

# Binder系列---服务添加过程(2)

# Binder系列---服务添加过程(3)