美文网首页
Android 03--IPC进程间通信基础简介

Android 03--IPC进程间通信基础简介

作者: 熠闲 | 来源:发表于2018-12-06 11:41 被阅读9次

    IPC是Inter-Process Communication简写,意为进程间通信/跨进程通信,指代不同进程里面进行数据交换。因为该主题非常庞杂,所以分成多篇文章进行阐述,文章要点结构如下:

    1.进程与线程

    2.IPC的需求场景与常见系统的IPC机制

    3.Android多进程模式部分简述

    4.序列化与反序列化—Serializable与Parcelable接口

    5.Binder与AIDL简介

    6.IPC方式及其对比

    当然通过这些并不能完全介绍完IPC机制,但是作为抛砖引玉的入门知识应该还是可以的,详细的可以自行搜索,或者阅读参考书籍与参考博客,如有错误,敬请指出。

 1.进程与线程

    进程是一般是指系统中的一个执行单元,在pc或者移动设备上通常情况下可指代一个应用;线程则是CPU里最小的执行单元,它是一种有限的系统资源。通常情况下,一个进程能拥有多个线程,二者存在包含关系。

    在这里补充一下,Android中开辟新线程一般只有在AndroidManifest文件中给四大组件进行android:process进行指定,可以视为常规下的唯一手段。android:process的值也具有一些默认规定,当其值以“:”开头,则视为应用私有线程,其他应用的组件不能和它泡在同一个线程里面,而不以“:”开头则视为全局线程,其他应用可以通过ShareUID方式与他跑在同一个线程里面(UID是进程的标识,当不同应用具有相同ShareUID与签名时候,应用才能相互访问对方私有数据)。当然,也可以通过JNI在native进行fork一个新线程,但是这种方法属于特殊情况,非常用方式。

2.IPC的需求场景与常见系统的IPC机制

    当操作系统中某些任务需要单独的进程进行,某些应用因为过大而且系统对应用存在内存限制,不同应用中需要进行跨进程的通信,这时候就需要IPC进行解决(系统提供的ContentProvider去查询数据)。

    当然不止Android需要采取IPC机制,所有操作系统都需要对应的IPC机制,如Linux上可以运用命名管道,共享内容,信号量等,Window吸用可以通过剪切板,管道和邮槽等。Android虽然基于Linux系统,但是他的IPC机制并不完全继承于Linux,而且拥有自己读的进程间通信方式。Android自己特有的IPC方式就是Binder了,当然还有其他的方式如Socket进行不同端的通信(也可以用于同端不同进程通信)。

3.Android多进程模式部分简述

    应用的多进程开始方式在上头我们简单说明过了,但是我们一般很少采用开辟新进程,不仅因为其对应的开销比较大,还具有许多需要克服的困难和问题。一般来说,多进程会遇到下面几种问题:

    (1)所有静态数据与单例模式全部失效;

    (2)SharePreference的可靠性下降;(SP的底层机制是通过读写XML文件实现,多进程容易导致并发读写出现问题)

    (3)线程的同步机制失效;(本质上与1是一致的,因为1的问题,所以无论是锁对象还是锁全局类都无法保证线程同步,造成该问题)

    (4)Application会被多次创建;

4.序列化与反序列化—Serializable与Parcelable接口

    序列化是将数据对象的状态信息转化成可存储或者传输的形式,多是字节或者xml格式。对象序列化机制是java内建的一种对象持久化机制,通过它可以将对象状态转化成字节数组,需要的时候再通过反序列化将字节数组转化成对象。对象的序列化可以很容易地在jvm里的活动对象与字节数组(流)的相互转化。

    其中Serializable与Parcelable接口均是为了库本身锁提供的序列化接口:

    (1)Serializable

            数据对象类只需要对接该接口,则完成序列化。其序列化与反序列化都由内部自行实现。我们可以自行选择是否要在对象类中指定serialVersionUID,指定与否都可以完成序列化,但是当数据原型类发生结构改变时,会有不可忽略的影响。

            serialVersionUID是用于辅助序列化与反序列化过程的 ,原则上唯有序列化后数据里的serialVersionUID与对应类的serialVersionUID一致才能进行反序列化过程,否则将会发生反序列化失败,程序会出现crash。当我们没有指定serialVersionUID时候,系统在序列化时会根据类的结构计算当前类的hash值并赋予serialVersionUID,这时候如果我们结构发生改变(一般修改如增加、删除成员变量),就会造成对应的前后hash值不一致,反序列化 将会失败,通常会造成程序挂掉。尤其是发生重大结构改变(类名修改,成员变量),此情况下反序列化必定造成程序崩溃。所以当指定serialVersionUID后就能避免这种情况,当然发生改变的地方相对应的默认处理(如增加了某个变量,反序列化后该变量值为空)。

    (1)Parcelable

            数据对象对接该接口,就需要实现两个:writeToParcel与CREATOR。Pracel内部包装了可序列化的数据,可供Binder进行传输。由此可知writeToParcel是用于序列化过程,CREATOR则用于反序列化过程。系统也提供了许多实现了Parcelable接口的类,如Intent,Bundle,Bitmap等,List和Map也可以序列化,但是其里面的每个元素都是可序列化的。

        综上,二者都是可以实现序列化的,当然要某个数据模型类实现可序列化,其成员也都需要是可序列化元素。其中Serializable为Java中的序列化接口,Parcelable则属于Android提出的。他们之间的取舍也有一定差异:

        Serializable使用简单但是开销很大,需要大量I/O操作;

        Pracelable则更适用于Android平台,效率很高,但是使用麻烦。

    5.Binder与AIDL简介

        Binder是Android里的一种进程间通信(IPC)的机制,并非单纯的一个东西,可以理解成是一套东西。以IPC角度看,它是一种“设备”,用于实现数据传递机制。以Android应用层来看,是客户端与服务端的一种媒介,用于连接各种Manager(如ActivityManageer、WindowManager等)与ServiceManager,类似于桥梁的作用,其与TCP/IP中一个典型的服务连接过程十分相似。Binder大体上可以由下列组成

Binder驱动→路由器:

Service Manager→DNS

Binder Client→客户端

Binder Server→服务器

(详细可见参考博客)

Binder的场景示意图

        客户端线程1发送请求,启用bindservice时候,通过ServiceManager查找到服务端线程2,之后服务端会返回一个包含Binder对象,从servicemanager获取客户端位置,通过binderservice将数据,服务传递给客户端。

        当然Binder里所传递的服务一般分成普通服务和AIDL服务。当然Binder并不是非要用于进程间通信,一般不涉及进程间通信,如Binder常用于Service中,普通的Service并不单独于新的进程,但这种不涉及Binder的核心。接下来我们解释一下AIDL:

        AIDL是Android Interface Definition Language(Android接口定义语言)的缩写,用于定义服务端与客户端的通信一种描述性语言,更具体地来说是Android用于进程间通信的一种模板。当然AIDL支持的类型有:

            (1)八种基本数据类型:byte、char、short、int、long、float、double、boolean

            (2)String,CharSequence

            (3)实现了Parcelable接口的数据类型

            (4)List 类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

            (5)Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

        补充一下,AIDL文件以 .aidl 为后缀名,但是起作用的并不是AIDL文件,而是系统通过aidl文件所生成的java文件。

6.IPC方式及其对比

(1)Bundle:

        优点:简单易用

        缺点:只能传输Bundle支持的数据类型

        适用场景:四大组件之间的进程通信

(1)文件共享:

        优点:简单易用

        缺点:不适合高并发场景,无法做到进程间的即时通信

        适用场景:无并发的访问情景,交换的数据为实时性不高的场景

(1)AIDL:

        优点:功能强大,支持一对多并发通信,支持实时通信

        缺点:使用比较复杂,需要处理好线程同步问题

        适用场景:一对多通信,且有RPC需求

(1)Messenger:

        优点:功能一般,支持一对多串行通信,支持实时通信

        缺点:不能很好地处理高并发场景,不支持RPC,数据通过Message进行传输,因此只能传输bundle支持的数据类型

        适用场景:低并发的一对多即时通信,无RPC需求,或者无需返回结果的RPC需求

(1)ContentProvider:

        优点:数据源访问方面功能强大,支持一对多并发数据共享,可通过Call方法扩展其他操作

        缺点:可视为受约束的AIDL,主要提供数据源的CRUD(Create、Read、Update、Delete)操作

        适用场景:一对多的进程间的数据共享

(1)Socket:

        优点:功能强大,可进行网络传输字节流,支持一对多并发即时通信

        缺点:实现繁琐,不支持直接的RPC

        适用场景:网络数据交换

目前理解的仍很粗浅,如有错误敬请指正,详细的可见参考书籍和参考博客。

---------------------

参考书籍:《Android开发艺术探索》

参考博文:

作者:ClAndEllen  来源:CSDN   题目:Android面试系列文章2018之Android部分Binder机制篇

链接:https://blog.csdn.net/ClAndEllen/article/details/79343389

---------------------

相关文章

网友评论

      本文标题:Android 03--IPC进程间通信基础简介

      本文链接:https://www.haomeiwen.com/subject/wtuwcqtx.html