1. 什么是Android IPC
- IPC:inter-process Commnication跨进程的通信,多进程之间的通信,不同的操作系统有不同的通信方式,Android继承自Linux,但其IPC并没有完全继承Linux,除了socket进程通信之外,其最具特色通信方式之一的是binder机制
- 为什么需要进程通信:我们知道Android一般情况下一个应用是默认运行在一个进程中,但有可能一个应用中需要采用多进程模式来实现(比如获取多份内存空间),或者两个应用之间需要获取彼此之间的数据,还有AMS(系统服务)对每个应用中四大组件的管理,系统服务是运行在一个单独的进程中,这些统统需要IPC
- Android在一个应用中开启多线程模式
- 为四大组件在Android Manifest中指定Android:process属性,进程名以 : 开头的进程属于当前应用的私有进程,其他应用的组件不可以和它在同一个进程中,进程名不以: 开头的属于全局进程,其他应用可以通过ShareUID方式跑在一个进程中,这意味着可以共享内存数据。
- 多进程运行:我们知道Android为每一个进程独立分配了一个独立的虚拟机,所以在内存分配上是有不同的地址空间,所以运行在不同进程的四大组件,他们之间没办法共享数据,因此我们需要进程间的通信
- Android进程间通信方式包括:通过intent传递数据,共享文件和sharedPreference,基于binder的message和AIDL还有socket
2. IPC 基础概念
Serializable和Parcelable接口可以完成对象的序列化。
序列化是指将一个对象转化为二进制或者是某种格式的字节流,将其转换为易于保存或网络传输的格式的过程,反序列化则是将这些字节重建为一个对象的过程。
在Android中,intent和Binder在传输数据的时候就需要将对象实现parcelable或者serializable接口。
- Serializable接口:
- Java提供的序列化接口,使用时只需要实现Serializable接口并声明一个serialVersionUID(用于反序列化)
- 使用方法
Parcelable接口:
Android中Parcelable接口用法两者都可以实现序列化并可用于intent间的数据传递,Serializable使用简单,但是开销很大,Parcelable是Android中的序列化方式,使用起来麻烦一点,但是效率很高,是Android推荐的方式。Parcelable主要用在内存序列化上,如果要将对象序列化到存储设备或者通过网络传输也是可以的,但是会比较复杂,这两种情况建议使用Serializable。
- Binder机制:为什么Android 要采用Binder作为IPC机制?
- 性能:Binder数据拷贝只需要一次,而管道、消息队列和socket都需要2次,共享内存不需要一次内存拷贝,从性能角度来看,binder性能仅次于共享内存。
- 稳定性:Binder基于C/S 架构 ,server端与client端相对独立,共享内存需要考虑访问临界资源的并发同步问题,binder结构的稳定性较好
安全性:Android为每个人应用程序分配了自己的UID,进程的UID是鉴别进程身份的重要标志,Android系统中对外只暴露Client端,Client端将任务发送给Server端,Server端会根据权限控制策略
Android OS中的Zygote进程的IPC采用的是Socket(套接字)机制,Android中的Kill Process采用的signal(信号)机制等等。而Binder更多则用在system_server进程与上层App层的IPC交互。
Binder在Android系统中江湖地位非常之高。在Zygote孵化出system_server进程后,在system_server进程中出初始化支持整个Android framework的各种各样的Service,而这些Service从大的方向来划分,分为Java层Framework和Native Framework层(C++)的Service,几乎都是基于BInder IPC机制。
- Java framework:作为Server端继承(或间接继承)于Binder类,Client端继承(或间接继承)于BinderProxy类。例如ActivityManagerService(用于控制Activity、Service、进程等) 这个服务作为Server端,间接继承Binder类,而相应的ActivityManager作为Client端,间接继承于BinderProxy类。 当然还有PackageManagerService、WindowManagerService等等很多系统服务都是采用C/S架构;
- Native Framework层:这是C++层,作为Server端继承(或间接继承)于BBinder类,Client端继承(或间接继承)于BpBinder。例如MediaPlayService(用于多媒体相关)作为Server端,继承于BBinder类,而相应的MediaPlay作为Client端,间接继承于BpBinder类。
3. Android 中的binder
参考:
Binder系列—开篇
可能是讲解Binder机制最好的文章
Android Bander设计与实现 - 设计篇
Android - Binder驱动
3.1 面向对象的binder IPC
- Binder使用C/S 模式,一个进程作为server提供诸如视频解码,网络连接、查询等多种服务,多个进程作为client向server发起服务请求,获得所需要的服务。
- Binder的独特之处在于Binder对象是一个可以跨进程实现的的对象,它的实体位于一个进程中,而它的引用则在其他client进程中,Binder驱动为面向对象的进程间通信提供底层支持。
3.2 Binder通信框架
Binder框架定义了四个角色,Server,Client,ServiceManager,以及binder驱动,驱动运行在内核空间,其他三者运行在用户空间。
- Binder 驱动:binder驱动与硬件设备没有关系,但是它的工作方式与设备驱动程序是一样的,工作在内核态,提供open(),mmap(),ioctl等标准文件操作,用户可以通过/dev/binder来访问它,驱动负责进程之间binder通信的建立,传递,计数管理以及数据的传递交互等底层支持。
- ServiceManager:将Binder名字转换为client中对该binder的引用,使得client可以通过binder名字获得server中binder实体的引用。
- Client和Server在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信
- Server创建了Binder实体,为其取一个字符形式,可读易记的名字,将这个Binder连同名字以数据包的形式通过Binder驱动发送给SMgr,通知SMgr注册一个名叫张三的Binder,它位于某个Server中。驱动为这个穿过进程边界的Binder创建位于内核中的实体节点以及SMgr对实体的引用,将名字及新建的引用打包传递给SMgr。SMgr收数据包后,从中取出名字和引用填入一张查找表中。
- Server向SMgr注册了Binder实体及其名字后,Client就可以通过名字获得该Binder的引用