佛山h5建站模板,网站技术架构图,快速建设网站免费视频教程,企业网站后端模板IPC
IPC为 (Inter-Process Communication) 缩写#xff0c;称为进程间通信或跨进程通信#xff0c;指两个进程间进行数据交换的过程。安卓中主要采用 Binder 进行进程间通信#xff0c;当然也支持其他 IPC 方式#xff0c;如#xff1a;管道#xff0c;Socket#xff0…IPC
IPC为 (Inter-Process Communication) 缩写称为进程间通信或跨进程通信指两个进程间进行数据交换的过程。安卓中主要采用 Binder 进行进程间通信当然也支持其他 IPC 方式如管道Socket文件共享信号量等。
Binder简介
1.为什么使用Binder
性能方面 在移动设备上性能受限制的设备比如要省电广泛地使用跨进程通信对通信机制的性能有严格的要求Binder相对于传统的Socket方式更加高效。Binder数据拷贝只需要一次而管道、消息队列、Socket都需要2次共享内存方式一次内存拷贝都不需要但实现方式又比较复杂。 Binder传输数据的过程一次拷贝 Socket传输数据的过程两次拷贝 安全方面 传统的进程通信方式对于通信双方的身份并没有做出严格的验证比如 Socket 通信的IP地址是客户端手动填入很容易进行伪造。然而Binder机制从协议本身就支持对通信双方做身份校检从而大大提升了安全性。 2.Binder原理
从进程角度来看IPCInterprocess Communication机制 每个Android的进程只能运行在自己进程所拥有的虚拟地址空间。例如对应一个4GB的虚拟地址空间其中3GB是用户空间1GB是内核空间。当然内核空间的大小是可以通过参数配置调整的。对于用户空间不同进程之间是不能共享的而内核空间却是可共享的。Client进程向Server进程通信恰恰是利用进程间可共享的内核内存空间来完成底层通信工作的。Client端与Server端进程往往采用ioctl等方法与内核空间的驱动进行交互。 Binder通信采用C/S架构从组件视角来说包含Client、Server、ServiceManager以及Binder驱动其中ServiceManager用于管理系统中的各种服务。架构图如下所示 Binder通信的四个角色
Client进程使用服务的进程。Server进程提供服务的进程。ServiceManager进程 ServiceManager 的作用是将字符形式的 Binder 名字转化成 Client 中对该 Binder 的引用使得 Client 能够通过 Binder 名字获得对 Server中Binder 实体的引用。 Binder驱动
驱动负责进程之间 Binder 通信的建立Binder在进程之间的传递Binder引用计数管理数据包在进程之间的传递和交互等一系列底层支持。 3.Binder间数据传递 进程间数据传递都是需要序列化的。Serializable 和 Parcelable 接口都可以完成序列化通过 Intent 和 Binder传输数据时候就需要使用 Serializable 和 Parcelable 。 区别和联系 Serializable 是 Java中提供的接口序列化和反序列化需要大量的 I/O 操作开销比较大。而 Parcelable 是安卓中的序列化方式效率高。Parcelable 主要用在内存序列化上Serializable 主要用在用于文件网络中传递。 Binder
Binder 是 Android 中的一个类实现了 IBinder 接口。
从 IPC 角度来说 Binder 是 Android 中的一种跨进程通信方式可以理解为一种虚拟的物理设备它的设备驱动为 /dev/binder。 从 Framework 的角度 Binder 是 ServiceManager 连接各种 Manager(ActivityManagerWindowManager) 和 ManagerService 的桥梁。 从应用层的角度 Binder 是客户端和服务端进行通信的媒介当 bindService 时服务端会返回一个包含了服务端业务调用的 Binder 对象通过这个 Binder 对象客户端就可以获取服务端提供的服务或者数据包括普通服务和 AIDL 服务。 Android中IPC方式
1.使用 Bundle Bundle 实现了 Parcelable 接口可以通过 Intent 进行传递。当从一个进程启动另一个进程的 Activity 时可以在 Bundle 中附加参数这些数据必须是能够被序列化的。
2.使用文件共享 A进程往文件中写数据B进程从文件中读数据。在 Windows上一个文件如果被加了排斥锁将会导致其他线程无法对其进行访问。而 Andorid 是基于 Linux是的其支持并发 读/写 可以无限制的进行但是需要注意并发安全问题。
SharedPreferences 是 Android中轻量级的存储方案通过键值对来存储数据采用 xml 文件来保存键值对。因为 Android 系统对 读/写 有一定的缓存策略即在内存中会有一份 SharedPreferences 文件的缓存在多进程下系统对它的读写变得不可靠。SharedPreferences 的 get 个 put 方法都是经过 synchronized 修饰的。
3.使用 Messenger Messenger 也被翻译为信使通过它可以在不同的进程间传递 Message 对象在 Message 中放入我们需要传递的数据。它的底层也是常用 AIDL。
服务端通过 Handler 创建一个 Messenger然后在 Servce 的 onBind 方法中返回这个 Messenger 对象的底层的 Binder即可。客户端通过服务端返回的 IBinder 就可以创建 Messenger来服务端发消息了。
4.使用 AIDL
AIDL 意思即 Android Interface Definition Language翻译过来就是Android接口定义语言是用于定义服务器和客户端通信接口的一种描述语言可以拿来生成用于IPC的代码。从某种意义上说AIDL其实是一个模板因为在使用过程中实际起作用的并不是AIDL文件而是据此而生成的一个IInterface的实例代码AIDL其实是为了避免我们重复编写代码而出现的一个模板
进程间的通信速度快(系统底层直接是共享内存)性能稳效率高一般进程间通信就用它. AIDL是Binder机制向外提供的接口目的就是为了方便对Binder的使用.
5.使用 ContentProvider ContentProvider 是 Android 提供的专门用于不同应用间进行数据共享的方式它的底层实现也是 Binder。
6.使用 Socket Socket 也被称为 “套接字”分为流式套接字和用户数据报套接字两种分别对应于网络传输控制层中的 TCP 和 UDP协议。
IPC各种方式比较 Binder连接池
在这种模式下整个工作机制是这样的每个业务模块创建自己的AIDL接口并实现此接口这个时候不同业务模块之间是不能有耦合的所有实现细节我们要单独开来然后向服务端提供自己的唯一标识和其对应的Binder对象对于服务端来说只需要一个Service就可以了服务端提供一个queryBinder接口这个接口能够根据业务模块的特征来返回相应的Binder对象给它们不同的业务模块拿到所需的Binder对象后就可以进行远程方法调用了。由此可见Binder连接池的主要作用就是将每个业务模块的Binder请求统一转发到远程Service中去执行从而避免了重复创建Service的过程它的工作原理如图所示。 Binder的使用
定义接口
Binder机制通常用于实现进程间的接口调用,我们需要先定义Binder接口。一个典型的Binder接口如下:
public interface IBookManager {public void addBook(Book book);public void deleteBook(int bookId);public Book getBook(int bookId);public ListBook getBooks();
}这是一个书管理的Binder接口,包含增加书籍、删除书籍、获取书籍等方法。
实现Binder接口
然后我们需要实现上面的Binder接口,并继承自Binder类,这样这个类的实例就代表了一个Binder实体,可以跨进程传输。
public class BookManager extends Binder implements IBookManager {public void addBook(Book book) { ... }public void deleteBook(int bookId) { ... }public Book getBook(int bookId) { ... }public ListBook getBooks() { ... }
} 在Server端注册Binder实体
在提供服务的进程内,我们需要将Binder实体注册到ServiceManager中。这样当其他进程想访问这个Binder实体时,就可以从ServiceManager中获取它。
public class BookManagerService extends Service {private final BookManager bookManager new BookManager();public void onCreate() {super.onCreate();publishBinderService(CMD_BOOK_MANAGER, bookManager);}
}在onCreate()方法中我们通过publishBinderService()方法将bookManagerBinder实体发布到ServiceManager中,这样其他进程就可以通过CMD_BOOK_MANAGER这个key来获取这个Binder实体了。
在Client端获取Binder代理并调用
在客户端进程中,我们可以通过ServiceManager访问Server发布的Binder实体。
public void queryBookManager() {// 获取ServiceManager的代理IBinder service ServiceManager.getService(CMD_BOOK_MANAGER);// 通过服务端返回的IBinder对象生成Binder代理IBookManager bookManager IBookManager.Stub.asInterface(service);// 通过代理调用服务端的方法ListBook books bookManager.getBooks();...
} 我们首先通过ServiceManager获取要访问的Binder实体,这个会返回一个IBinder对象。然后通过IBookManager.Stub.asInterface(service)将IBinder对象转成客户端所需的IBookManager接口类型,这个对象就是Binder代理。我们可以通过这个代理对象调用服务端IBookManager接口中的方法。
至此,我们完成了一个跨进程的Binder通信的全过程。客户端通过Binder代理访问服务器提供的服务,服务器通过Binder实体来处理客户端的请求。这整套机制都建立在Binder驱动之上,Binder驱动负责将双方的请求和回复进行传递。