Android Binder机制,共享内存实现原理

导读

  • 移动开发知识体系总章(Java基础、Android、Flutter)
  • IPC机制简介
  • IPC基础概念介绍
  • Binder
  • Binder连接池
  • Android中的多进程模式
  • Android中的几种IPC方式
  • AIDL的初步了解
  • C/S模式

IPC机制简介

IPC是Inter-Process Communication的缩写,含义就是跨进程通信。
按操作系统的描述,进程是资源分配的最小单位,而线程是CPU调度的最小单位,在Android中进程一般是指一个应用程序,一个进程可以包含一个或多个线程。每个Android应用都有一个主线程,也就是我们常说的UI线程,在主线程执行耗时操作会ANR(Application Not Response)。

  • IPC(进程间通信)机制不是Android系统所独有的,其他系统也有相应的进程间通信机制。
  • Android系统架构中,大量采用了Binder机制作为IPC,是Android系统中最重要的组成。
  • 当然也存在部分其他的IPC方式,比如Zygote通信便是采用socket。

Android系统中,每个应用程序是由Android的Activity,Service,Broadcast,ContentProvider这四大组件的中一个或多个组合而成,这四大组件所涉及的多进程间的通信底层都是依赖于Binder IPC机制。

我们使用多进程的原因不外乎两种:

第一种情况是一个应用因为某些原因自身需要开启多进程模式,比如某些模块需要单独运行在一个独立的进程中,又或者是为了获取更多可使用内存而开启新进程。我们不用担心某个应用会占用系统过多的内存资源,因为Android系统对单个应用能使用的最大内存做了限制。

第二种情况是两个不同的应用之间需要进行数据交互,不同的应用本身就是两个不同的进程,因此就必须要使用进程间通信方式来达到数据交换的目的。

总之,我们应该谨慎地使用多进程技术,一旦我们采用了多进程的设计方法,我们就必须要妥善地处理进程间通信的各种问题。


IPC基础概念介绍

主要包含三部分:Serialiazable,Parcelable以及 Binder

Serializable和Parcelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据的时候就需要对数据进行序列化处理。还有的时候我们需要将数据持久化保存到本地或者通过网络传输给其他终端,我们也需要Serializable完成对象的持久化。

Serialiazable:Java提供的序列化接口(标记接口)
Parcelable:android提供的序列化接口

Serializable 与 Parcelable对比

  • Serializable 是Java中的序列化接口,使用起来简单;Parcelable是Android中的序列化方式,使用起来稍微复杂一些。
  • Serializable 在序列化操作的时候会产生大量的临时变量,从而导致GC的频繁调用(原因是使用了反射机制);Parcelable是以Ibinder作为信息载体的,在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable
  • 将对象序列化到存储设备上或者序列化后通过网络传输,使用Parcelable 会稍显复杂,因此这两种情况建议使用Serializable

Binder

直观的看,Binder是Android中的一个类,实现了IBinder接口
从不同角度理解Binder:
1 从IPC角度,Binder是跨进程通信方式
2 从FrameWork角度,Binder是ServiceManager连接各种Manager(如am,wm
)等的桥梁
3 从应用层角度,Binder是客户端与服务端通信的媒介


从进程角度来看IPC机制

Android Binder机制,共享内存实现原理_第1张图片
IPC原理

每个Android的进程,只能运行在自己进程所拥有的虚拟地址空间。对于用户空间,不同进程之间彼此是不能共享的,而内核空间却是可共享的。Client进程向Server进程通信,就是利用进程间可共享的内核内存空间来完成底层通信工作的,Client端与Server端进程往往采用ioctl等方法跟内核空间的驱动进行交互。


Android中的几种IPC方式

  • 使用Bundle
  • 使用文件共享
  • 报文队列(Messenger)
  • 使用AIDL
  • 使用ContentProvide

使用Bundle

在Android开发中,我们通常会使用Bundle在不同的组件中传递一些数据,由于Bundle 本身已经实现了Parcelable 接口,所以它可以很方便地在进程间传输。当我们在一个进程中启动了另一个进程的Activity、Service和Receiver,我们可以将需要传输的数据放入Bundle中并通过Intent传递出去。使用示例:

private void startMain() {
    Intent intent = new Intent(FirstActivity.this, MainActivity.class);
    Bundle bundle = new Bundle();
    bundle.putString("key", "value");
    ……
    intent.putExtra("bundle", bundle);
}

我们必须要知道,我们传输的数据必须是可序列化的,比如基本类型、实现了Serializable 或Parcelable接口的对象以及一些Android支持的特殊对象,具体可以查看Bundle 这类中的一系列put 方法。Bundle 不支持的数据类型我们无法通过它在进程间传递。

使用文件共享

两个进程可以通过读/写同一个文件来交换数据,也就是说A进程把数据写入到共享文件中,B进程通过读取共享文件获取A进程共享的数据。

由于Android系统是基于Linux的,使得并发读写可以没有限制地进行,甚至两个线程对同一个文件进行写操作都是可以的,尽管这样可能会使数据变得杂乱。除了交换一些文本信息,我们还可以序列化一个对象到文件系统中,之后在另一个进程中恢复这个对象,虽然两个对象内容完全相同,但是得到的对象和之前的对象本质上是两个不同的对象。

通过文件共享实现进程间通信的局限性也是比较明显的:当多个线程并发读写文件,那么我们得到的数据就可能不是正确的。所以在使用这项技术的时候,我们应该尽量避免并发读写这种情况的发生,或者只在对数据同步要求不高的情况下使用文件共享来实现进程间通信,并且妥善处理并发读写问题。

使用Messenger

使用AIDL

使用ContentProvider

ContentProvider 是Android中提供的专门用于不同进程间数据共享的方式,ContentProvider作为Android中的四大组件之一,可见它在Android中是比较重要的。它的底层实现同样是Binder,但是它的使用过程比AIDL方便得多,因为系统为我们做了封装,使得我们不需要关心底层细节就可以轻松实现进程间通信。

系统也为开发者提供了很多内置的ContentProvider ,例如通讯录、相册信息等,要跨进程访问这些数据,我们就必须先了解ContentProvider 的创建以及使用规则。

总结
IPC是什么?是跨进程通信
AIDL是什么?是IPC方式的一种
IPC为什么会导致那么多问题?内存独立
我们在什么时候需要IPC?某功能需要运行在独立进行;提升应用分配内存;应用间交互

你可能感兴趣的:(Android Binder机制,共享内存实现原理)