您的位置:首页 > 移动开发 > Android开发

Android Framework 基于 IPC Binder驱动使用 RPC

2016-05-16 18:22 295 查看
先来点高大上的普及:

何谓IPC

在Linux中,是以进程为单位分配和管理资源的。出于保护机制,一个进程不能直接访问另一个进程的资源,也就是说,进程之间互相封闭。但是,一个复杂的应用系统中,通常会使用多个相关的进程来共同完成一项任务,因此要求进程之间必须能够互相通信,从而共享资源和信息。所以,操作系统内核必须提供进程间的通信机制(IPC)。

何谓RPC

Android的RPC并不需要实现不同主机或不同操作系统间的远程调用,所以、它属于一个轻量级的RPC。

Android系统的RPC = Binder进程间通信 + 在Binder基础上建立起来的进程间函数调用机制。

我要讲的课题就是说白了: 进程A 通过ServiceManager调用进程B实现的接口,使用的是Binder驱动。
先介绍ServiceManager,
如以下代码,Android启动脚本在开机时候,默认启动此项服务。



是的,你看到了main函数。
353行: binder_open 打开binder驱动程序,就像你open("/dev/led",r);那么简单
359行: 告诉使用binder驱动的我们即将介绍的A和B进程,洒家是manager哦。
364行--383行: 安全相关,不在讨论范围,此处无需理会。
386行: binder_loop 从名字上看,是一个循环,重复做某些高尚的事情,说难听点在拉皮条。
大概能猜测, B告诉manager,我有某些接口(大姑娘,拿去用),比如print_hello.
manager把他放入(资源)链表
A进程问manager, 哥,我需要调用print_hello函数(大姑娘),你那可以介绍给我么?
manager这个死媒婆就把刚才的B的闺女介绍给A享用了。
不要忘记了,他们的对话都是基于Binder驱动,所以A,B进程都有一句底下353行binder_open();
合不合理啊。



我们来看看binder_loop在干啥子
for(;;)死循环,一直在找姑娘资源放在手里,然后介绍给各种A
378行: res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
ioctl哦,就是在数据交互啦。注意最后一个参数bwr, 这个结果体就是数据传输载体啦。
ioctl阻塞着,一直在路边等待,等待什么呢? 也许从binder驱动这边来一个B进程来介绍他的函数(闺女),也许是来一个A进程来找函数。
有数据返回时394行:binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
这个函数在做什么呢?
此情此景,大概知道
1. 如果是B进程,他是把函数注册过来,manager放入链表中去
2. 如果是A进程,查询链表,返回他需要的函数。
我们去看看代码,是否是这样的。



--------------------------------------------------------友好的分界线,底下是binder_parse--------------------------------------------
哥们,看到各种case了吗, binder_parse 根据case后面的各种指令做不一样的事情哦。
看到227行:case BR_TRANSACTION: 这个分支主要来处理函数的注册和分配哈。
看到234行:if (func) {
此处的func 是调用binder_parse的binder_loop传来的,调用loop处:binder_loop(bs, svcmgr_handler);
很容易,就能追踪到,this func is svcmgr_handler();
很自然,我们要看看svcmgr_handler()做了什么勾当。



。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。



---------------------------------------------------------------------------------华丽的分割线,以下svcmgr_handler的实现-----------------------------------------------
依然还是看到各种 case
还有友好的宏的名字:292 293行
case SVC_MGR_GET_SERVICE:

case SVC_MGR_CHECK_SERVICE: 从名字来看,A进程来通讯的时候,他的结构体里面必定带有此类宏,来告诉他,我来找啥子

273行:handle =
do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
通过do_find_service需找A要的函数,返回一个handle句柄。(其中的数据结构,哥另外一个章节分析)



。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。



-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以上就是servicemanager的基本框架。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

来获取服务的A进程做什么事情呢?
看看,也有main函数,也有bs = binder_open(128*1024);
174行:
handle = svcmgr_lookup(bs, svcmgr, "goodbye");

需找他需要的服务,叫做goodbye服务. 我写的goodbye服务里面提供两个接口: saygoodbye 和saygoodbye_to



A进程调用自己的saygoodbye,哈哈哈
大家这会儿明白了没, 此处的saygoodbye并非真正实现saygoodbye的具体功能,而是在做通信,在需找其他进程当中的saygoodbye。
这个就算远程调用啦,轻量级的RPC
通过107行: binder_call 来找goodbye服务里面,代号为GOODBYE_SVR_CMD_SAYGOODBYE的函数,并将需要传输的参数等放在msg中,在远端找到的B进程里面
执行。多么的高大上啊。
既然这样,我们肯定要分析binder_call做什么啦。
注意107行,binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE);美丽宏哦,给manager用,底下会用到



----------------------------------------------------------------------------华丽分割,以下binder_call源码-----------------------------------------------------------
做好数据交互对象bwr以后
351行: res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
注意332行: writebuf.cmd = BC_TRANSACTION;这个漂亮的宏就是告诉manager调用binder_parse函数里面的case BC_TRANSACTION,然后调用func,
也就是以上分析的svcmgr_handler
跟manager通信,把我要的东西放在bwr里面。
这样manager收到信息以后呢,就进入 到
case SVC_MGR_GET_SERVICE:

case SVC_MGR_CHECK_SERVICE:为他找到进程B,并且执行A想要的函数。



................................
.................................



好啦,以上就是A进程,我们称之客户端进程想servicemanager要服务B里面的接口的过程啦。

B进程怎么像manager注册呢,分析完了A,B就不是难事啦。

我简单贴上代码,自行分析哈。

217行: 熟悉的open bs = binder_open(128*1024);

224行: svcmgr_publish(bs, svcmgr, "hello", hello_service_handler); 这个接口用来发布B的接口



----------------------------------------------------------------------------------------------------------------------svcmgr_publish----------------------------

同样 29行有binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE)

但是注意 第三个参数: SVC_MGR_ADD_SERVICE加入服务 哇哈哈哈



大概的三者框架就是这样,其中具体的handle数据分析,等待哥哥下期分析啦。

微信: 18650711783

秋秋: 327022711
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: