1.举个例子
binder系统的核心有两个
IPC和RPC
IPC:进程间通讯,比如说A进程想把数据原原本本的发给B进程,这之间就涉及IPC
RPC:远程间调用,比如A进程想去打开led,他会调用led_open,然后调用led_ctl,但是他并没有权限打开驱动程序,他会怎么办呢?
1.他会封装数据,或者构造数据
2.发送给B,怎么发送,就是通过IPC通道发送给B进程
3.B进程收到以后,取出数据
4.然后B调用自己本地的led_open和led_ctl
数据传输有三大要素:
1.源
2.目的
3.数据本身
在我们的例子中,源就是进程A,目的就是进程B,现在问题来了,进程A怎么知道是进程B提供led的访问,如果进程A想操纵声音,他应该给哪个进程发送数据?
所以这里就会引入两个东西:
1.进程B向所谓的service manager注册服务led服务
2.进程A向service manager查询服务有没有led服务,得到一个handle,这个handle就是指向进程B
数据就是双方约定好的一个buf
对于binder系统,涉及到四个东西
1.A,就是client
2.B,就是server
3.A怎么知道向哪一个B发送数据,中间就引入了一个service manager
4.他们之间的通讯是通过binder驱动实现的
再看RPC:远程过程调用,认为是调用其他进程的某个函数就可以了
1.调用哪个函数:server的函数编号
2.传给它什么参数:通过IPC的buf传输
3.返回值
现在,我们看看具体的调用过程,在android源码包里面,有一些用c语言写的binder应用程序,我们可以参考他理解这整个调用过程。
源代码在这个目录里面:
http://androidxref.com/9.0.0_r3/xref/frameworks/native/cmds/servicemanager/
1.里面有一个service_manager.c
2.还有一个半成品bctest.c
3.还有一个封装好的c库binder.c
以后我们会根据这个半成品bctest.c,写出我们的client程序和server程序
现在我们先大概猜测一下,这个client,sever,servicemanager分别做什么事情
2.流程分析
我们之前那说过,首先server要向service manager注册一个服务,首先运行的肯定是service manager
1.第一步干嘛呢?应该去open binder驱动
2.告诉驱动程序,它就service manager
3.应该是一个while循环
a.读驱动获取数据,别人没有给他发数据的时候就休眠
b.读到数据后就解析数据
c.并且调用两个函数
c1.注册服务:首先server可能会向你注册服务,那么就在连表中记录名字
c2.获取服务:注册服务以后,client有可能会向你发出数据,想获得某个服务
c2a:在链表中查询有无服务
c2b:返回“server进程”的handle
再看看server会做什么事情
1.打开驱动程序
2.注册服务
a.向service manager发送服务的名字
3.while(1)循环,既然是一个服务,就要等待客户端给你发送数据,让你去解析这些数据来调用你的函数
a.读驱动获取数据,没有数据的时候就休眠
b.解析数据
c.调用对应的函数
再看看client
1.open 驱动
2.获取服务:我想把数据发送给服务进程,我发送给谁呢?
a.首先,我要向service manager查询,得到一个handle,
b.以后我就知道 ,我可以把数据发送给handle,这个handle对应这个服务进程
3.向handle发数据,最终会导致server读取到数据,他就会解析数据,然后调用他本地的函数,来实现他硬件的操作等等
我们分析了这整个调用过程,但是有个细节我们要留意一下,server注册服务的时候也要向其他进程发送消息,他要向service manager发送消息,他怎么知道service manager是谁?client他要获取服务,他也要向service manager发送消息,那么这个service manager是谁?所以,servicemanager本身要告诉驱动程序,它就service manager。
3.结合源码验证猜测
看看源代码,验证我们分析的对不对
http://androidxref.com/9.0.0_r3/xref/frameworks/native/cmds/servicemanager/service_manager.c
http://androidxref.com/9.0.0_r3/xref/frameworks/native/cmds/servicemanager/bctest.c
由于bctest是个半成品,所以只能分析到这里。