您的位置:首页 > 其它

Binder ServiceManager解析

2015-08-06 12:38 176 查看

1 Binder库介绍

在Binder库中,Service组件和Client组件分别使用模板BnInterface和BpInterface描述,其中前者成为Binder本地对象,后者成为Binder代理对象。Binder库中的Binder本地对象和Binder代理对象分别对应于Binder驱动程序中的Binder实体对象、Binder引用对象。

BpBinder类中有一个成员变量mHandle,代表一个Client组件的句柄值,每个Client组件在Binder驱动程序中都对应一个Binder引用对象,而每个引用对象都有个句柄值,其中Client组件就是通过这个句柄值来和Binder驱动程序中的Binder引用对象建立对应关系的。

BpBinder类的成员函数transact用来向运行在Server进程中的Service组件发送进程间通信的请求,这是通过Binder驱动程序间接实现的。BpBinder的成员函数transact会把BpBinder类的成员变量mHandle,以及进程间通信数据发送给Binder驱动程序,这样Binder驱动程序就能够根据这个句柄值来找到对应的Binder引用对象,继而找到对应的Binder实体对象,最后可以将进程间通信数据发送给对应的Service组件了。

无论是BBinder还是BpBinder都是通过IPCThreadState和Binder驱动程序交互的,每个使用Binder进程间通信机制的进程都一个Binder线程池,用来处理进程间通信请求。对于每一个Binder线程来说,它的内部都有一个IPCThreadState对象,我们可以通过IPCThreadState的静态成员函数self()获取,并且调用它的成员函数transact来和Binder驱动程序交互。在transact内部,与Binder驱动程序交互操作又是通过talkWithDriver来实现的,它一方面负责向Binder程序发送进程间的通信请求,另一方面又负责接收来自Binder驱动程序的进程间通信请求。

2 Binder机制运作的必要组成

client组件:通信请求的发起端。

service组件:通信请求的目标端。

Service Manager:服务的管理者。

binder驱动:进程间通信的执行者。

只有驱动运行在内核空间,其余的运行在用户空间

3 驱动中的两个重要数据结构

struct binder_node{
    ....
    void __user *cookie;
    ...
    };
struct binder_ref{
    ...
    struct binder_node *node;
    uint32_t desc;
    ...
    };


这里只是介绍和service manager工作原理相关的几个成员变量。binder_node代表binder实体对象,binder_ref代表binder引用对象,他们都是binder驱动里面的结构体。

cookie:指向service组件的用户地址空间

node:指向对应的binder实体对象

desc:binder引用对象的句柄值

那么这两个结构体是什么时候创建呢,在Binder机制的中篇中,我们已经介绍过,当binder驱动检测到传输的数据是binder实体对象的时候就会创建binder_node、binder_ref,并且这个binder_ref通过成员变量node指向binder_node

另外一个问题就是什么时候binder驱动中传输的数据是binder对象呢?答案就是注册service组件的时候,注册service组件的过程下文会介绍。

4 Service Manager工作机制

Service Manager根据核心的任务其实就是提供addService、getService函数,分别实现注册service组件和获取service组件。addService到底对Service Mangager这个大管家做了什么手脚?下面我们就解开其神秘面纱。

addService的调用者严格意义上来说是ServiceManager的代理,这个代理充当了client端,真正的Service Manager服务是server端。Service Manager服务启动的时候会将自己注册为服务的管理者,并且它对应的代理对象句柄规定就是0(这个不再展开介绍)。

addService传入的参数是service组件的名称和service组件对象,当进入到binder驱动层的时候,驱动就检测到传输的数据是binder对象,然后在内核中创建binder_node、binder_ref,需要注意的是,binder_ref中函数service组件的句柄值,然后驱动将这个service组件的名字和分配的句柄值传给server端,即Service Manager对象,Service Manager对象中有个链表svlist,类型如下:

struct svcinfo{
        struct svcinfo *next;
        void *ptr;
        struct binder_death death;
        unsigned len;
        uint16_t name[0];
    };


name字段记录service组件的名称,ptr是service组件的句柄。Service Manager一旦接收到binder驱动传输过来的service组件名称和句柄值就创建一个svcinfo节点,并放入svlist当中,这样一来当client端通过getService()查找组件的时候就可以返回binder本地对象。

对于复杂的文字描述可能看到早就不耐烦了,下面通过一个图描述addService所做的工作(电脑没装viso挺恶心,先手绘吧^_^):



了解了addService原理,再理解getService就水道渠成啦,client端拿着serice组件的名称和Service Manager通信,Service Manager在svclist中对比组件名称,找到其对应的句柄,最后将返回一个binder代理对象

5 总结

本文介绍了Serverice Manager在Binder机制中的作用,并不涉及binder驱动层面,比如binder通信比较重要的通信协议等,以后有时间再补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: