Android 进程间通信机制(一) IPC概念和模型

一. 前言

        一直想把Binder机制认识清楚, 但是它涉及Android系统的Framework, Native, kernel层,  就需要你要有 C++  C基础阅读底层源码的能力, 目前笔者的水平,对Binder 在Native 和kernel层的实现原理和机制也是懵逼状态, 真的是博大精深, 故现阶段先把看懂和理解清楚的整理出来, 重点归纳Binder在app层和Framework层实现机制.  后续在慢慢积累往底层去理解它吧.

    

二. IPC通信

        Binder作为Android系统提供的一种IPC(Inter-process communication)机制,无论从系统开发还是应用开发,都是Android系统中最重要的组成,也是最难理解的一块知识点.

        Android系统中,多进程间的通信都是依赖于底层Binder IPC机制,Binder机制是一种RPC方案。例如:当进程A中的Activity与进程B中的Service通信时,就使用了binder机制.

       

2.1 我们先引入第一个问题:  Android系统中有哪些IPC通信方式?

名称特点使用场景
Bundle只能传输实现了序列化或者一些Android支持的特殊对象适合用于四大组件之间的进程交互
文件不能做到进程间的即时通信,并且不适合用于高并发的场景适合用于SharedPreference以及IO操作
ContentProvider可以访问较多的数据,支持一对多的高并发访问,因为ContentProvider已经自动做好了关于并发的机制适合用于一对多的数据共享并且需要对数据进行频繁的CRUD操作
Socket通过网络传输字节流,支持一对多的实时通信,但是实现起来比较复杂适合用于网络数据共享
Messenger底层原理是AIDL,只是对其做了封装,但是不能很好的处理高并发的场景,并且传输的数据只能支持Bundle类型多进程、单线程且线程安全
AIDL功能强大,使用Binder机制,支持一对多的高并发实时通信,但是需要处理好线程同步一对多并且有远程进程通信的场景

2.2 安卓中既然这么多IPC通信方式,为什么推荐使用Binder呢?

Android系统的基础是Linux内核,而Linux中实现IPC的机制有管道、消息队列、共享内存、Socket、信号量、信号这些,为什么Android还要另起炉灶呢?主要是性能、安全、易用性等方面的原因。

性能上来说数据拷贝次数越少越好,什么是拷贝下文再介绍。传统IPC机制(Socket、管道、消息队列等)都是拷贝两次,共享内存虽然无需拷贝,但会有安全、死锁、易用性差等问题,Binder只需拷贝一次,因此性能仅次于共享内存优于Socket。

安全性上来说Binder会为每个APP分配唯一的UID,Binder根据UID可以找到对应APP,传统IPC依赖上层协议是不安全的,无法获得对方的UID从而不能鉴别身份。传统IPC访问接入点是开放的,相当于谁都可以访问;Binder既有实名服务又有匿名服务,实名就跟传统IPC一样,谁都可以访问,AMS、WMS都是实名服务,匿名类似于打滴滴,用户直接联系不到司机,需要通过滴滴(系统)平台拿到司机号码,通过系统拿到服务的代理对象,再通过代理对象找到服务。Binder实名和匿名区别在于有没有在ServiceManager注册,注册了即为实名,没注册称为匿名,我们自己使用AIDL等方式一般为匿名。

3种常用IPC机制对比

Binder共享内存Socket
性能一次拷贝无需拷贝两次拷贝
特点

基于C/S架构,

易用性高

控制复杂,

易用性差

传输效率低,

开销大

安全性

为每个APP分配UID,

同时支持实名和匿名

依赖上层协议,

访问接入点是开放的

不安全

依赖上层协议,

访问接入点是开放的

不安全

 如果想了解更多?  请参阅 为什么Android要采用Binder作为IPC机制?

三. Binder IPC原理

Binder通信采用c/s架构,从组件视角来说,包含Client、Server、ServiceManager以及binder驱动,其中ServiceManager用于管理系统中的各种服务。

Client进程
使用服务的进程。

Server进程
提供服务的进程。

ServiceManager进程
Android OS的整个服务的管理程序,在binder通信中ServiceManager的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。

任何service在被使用之前,均要向SM(Service Manager)注册。当客户端需要访问某个service时,应该首先向SM查询是否存在该服务。如果SM存在这个service,那么会将该service的handle返回给client,handle是每个service的唯一标识符。

Binder
一个进程的Binder线程数默认最大是16,超过的请求会被阻塞等待空闲的Binder线程。所以,在进程间通信时处理并发问题时,如使用ContentProvider时,它的CRUD(创建、检索、更新和删除)方法只能同时有16个线程同时工作

Binder驱动
驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。

Binder通信分层架构图

Binder架构也是采用分层架构设计, 每一层都有其不同的功能:

已 调用startService方法流程为例子, 引出跨进程通信的架构图

  • Java应用层: 对于上层应用通过调用AMP.startService, 完全可以不用关心底层,经过层层调用,最终必然会调用到AMS.startService.
  • Java IPC层: Binder通信是采用C/S架构, Android系统的基础架构便已设计好Binder在Java framework层的Binder客户类BinderProxy和服务类Binder;
  • Native IPC层: 对于Native层,如果需要直接使用Binder(比如media相关), 则可以直接使用BpBinder和BBinder(当然这里还有JavaBBinder)即可, 对于上一层Java IPC的通信也是基于这个层面.
  • Kernel物理层: 这里是Binder Driver, 前面3层都跑在用户空间,对于用户空间的内存资源是不共享的,每个Android的进程只能运行在自己进程所拥有的虚拟地址空间, 而内核空间却是可共享的. 真正通信的核心环节还是在Binder Driver.

四. 安卓系统IPC图

如上图,Android系统分成三层。最上层是application应用层,第二层是Framework层,第三层是native层。 由下图可知几点:
1、Android中的应用层和系统服务层不在同一个进程,系统服务在单独的进程中。

2、Android中不同应用属于不同的进程中。

Android应用和系统services运行在不同进程中是为了安全,稳定,以及内存管理的原因,但是应用和系统服务需要通信和分享数据。

优点

安全性:每个进程都单独运行的,可以保证应用层对系统层的隔离。

稳定性:如果某个进程崩溃了不会导致其他进程崩溃。

内存分配:如果某个进程以及不需要了可以从内存中移除,并且回收相应的内存。

五. Thanks

        上面是Binder机制架构知识点, 我们对进程间通信架构先有个总体印象,代码细节和实现再慢慢探究,  文章图是引用 gityuan博客:Binder系列7—framework层分析 - Gityuan博客 | 袁辉辉的技术博客

           

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值