标签:
在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驱动程序的进程间通信请求。
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组件的过程下文会介绍。
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代理对象
本文介绍了Serverice Manager在Binder机制中的作用,并不涉及binder驱动层面,比如binder通信比较重要的通信协议等,以后有时间再补充。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/getnextwindow/article/details/47314955