Android进程间通信

Android系统是基于Linux内核的,Linux系统也有着丰富的IPC方式的。Linux系统的IPC方式主要有以下几种:
1、管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,它允许无亲缘关系进程间的通信。
2、信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身。
3、报文队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
4、共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。
5、套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。
既然Linux系统已有这么些IPC方式,那Android为什么另辟蹊径,采用Binder机制实现进程间通信呢?我想主要是有两点原因:1、必须满足C/S模式;2、原有的IPC方式性能不够好,需要优化。那么什么是Binder呢?

一、Binder框架
Binder是一种架构,它提供了服务端接口、客户端接口和Binder驱动三个模块。一个Binder服务端实际上就是一个Binder类的对象,该对象内部启动一个线程,主要用于接收Binder驱动发送的消息,收到消息后,将执行Binder对象中的onTransact()函数,并按照该函数的参数执行不同的服务代码。再看看Binder驱动,任何一个服务端Binder对象被创建时,同时会在Binder驱动中创建一个mRemote对象,该对象的类型也是Binder类,客户端要访问远程服务时,必须获取远程服务在Bdiner对象中的mRemote引用。获取到mRemote对象后,就可以调用transact()方法,在Binder驱动中,mRemote对象也重载了transact()方法,重载内容主要是以下几项:
1、以线程之间message的模式,向服务端发送客户端传过来的参数。
2、挂起当前线程,也就是客户端线程等待通知。
3、接收到服务端线程的通知,继续执行客户端代码。
对于开发人员来说,客户端似乎是直接调用远程服务对应的Binder,其实是通过Binder驱动进行了中转,即存在两个Binder对象,一个是服务端的Binder对象,还有一个是Binder驱动中的Binder对象。

二、ServiceManager
客户端想要使用一个系统服务,也就是和远程服务进行通信,首先要使用到的是ServiceManager,那么SM的职责是什么呢?系统服务的管理维护者。ServiceManager是一个独立进程,管理着系统各种服务。任何service在被使用之前,均要向SM注册,同时客户端需要访问某个service时,应该首先向SM查询是否存在该服务。如果SM存在这个service,那么会将该service的handle返回给client,handle是每个service的唯一标识符。SM本身也是一个Service,Framework提供了一个系统函数,可以获取到该Service对应的Binder引用,也就是BinderInternal.getContextObject(),该静态函数返回ServiceManager后,就可以通过ServiceManager提供的方法获取其他Service的Binder应用。SM的主要工作有:
1.初始化binder,打开/dev/binder设备。
2.指定SM对应的代理binder的handle为0,当client尝试与SM通信时,需要获取到这个handle为0的代理binder。
3.通知binder driver(BD)使SM成为BD的context manager。
4.维护一个死循环,在这个死循环中,不停地去读内核中binder driver,查看是否有可读的内容;即是否有对service的操作要求, 如果有,则调用svcmgr_handler回调来处理请求的操作。
5.SM维护了一个service list列表来存储service的信息。
这里写图片描述

三、MediaService实例
我们以MediaService为例,简单看一下它的源码。

int main(int argc, char** argv)
{
  //获得一个ProcessState实例
  sp<ProcessState> proc(ProcessState::self());
  //得到一个ServiceManager对象
  sp<IServiceManager> sm = defaultServiceManager();
  //初始化MediaPlayerService服务
  MediaPlayerService::instantiate();
  ProcessState::self()->startThreadPool();//启动Process的线程池
  IPCThreadState::self()->joinThreadPool();
}

1、ProcessState
ProcessState是一个单例模式,故每个进程只能有一个ProcessState对象。它的主要功能是 1.创建一个thread,该线程负责与内核中的binder模块进行通信,称该线程为Pool thread;2.为指定的handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。
2、Pool thread
ProcessState::self()->startThreadPool();执行这段就启动了一个Pool thread,在IPC中,所有进程均会启动一个thread来负责与BD来直接通信,也就是不停的读写BD。
3、BpBinder
BpBinder主要功能是负责client向BD发送调用请求的数据。它是client端binder通信的核心对象,通过调用transact函数向BD发送调用请求的数据。
4、IPCThreadState
ProcessState中有2个Parcel成员,mIn和mOut,Pool thread会不停的查询BD中是否有数据可读,如果有将其读出并保存到mIn,同时不停的检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到BD中,ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向mOut中写入数据。IPCThreadState有两个重要的函数,talkWithDriver函数负责从BD读写数据,executeCommand函数负责解析并执行mIn中的数据。
看到网上有一张图画得很清晰,借鉴过来学习一下。
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值