为什么要引入多进程
现今大型项目App都采用多进程的形式,正应为“大”,当单进程内存占用大时被系统Kill的几率也会增大,因而让单个组件运行在单独的进程中可以有效保活;还有,当子进程意外Crash主进程也不会因此而Crash,大大提高了App的健壮性;此外,当主进程退出服务子进程还可以在后台做推送消息等工作。
什么是Binder?
给出Binder一词的含义需要分场合,宏观来讲Binder是Android特有的一种进程间通信机制(或模型、框架),基于开源框架OpenBinder实现,它是实现进程间通信的一种规范。而在Binder机制中,Binder的含义分为以下几种:
- 从Android应用层来说,Binder是Client 和Server间通信的媒介:在bindService时Server会返回一个叫可以让Client获取Server所提供服务的Binder对象;
- 从Android FrameWork层来说,Binder是ServiceManager连接各类ManagerService的桥梁;
- 从Android Linux Kernel层来说,Binder是一种虚拟的物理设备即Binder驱动;
为什么要用Binder?
进程隔离
Android系统基于Linux,而Linux为保证进程的安全性,进程与进程之间的内存是不共享的,无法直接对数据进行操作,这就是进程隔离技术。
Binder较其他IPC机制的优势
- 性能:较Pipe、socket 和消息队列的复制2次来说,Binder在通信时只需复制1次,即进程A只需将数据通过copy_from_user()将数据复制到由Binder驱动在内核空间开辟的内核缓冲区内,之后数据会通过mmap()方法映射到目标进程B的用户空间,而前几种方法没有使用mmap,而映射2次复制0次的共享内存存在即为繁琐的进程同步问题,频繁的加锁会影响运行效率;
- 稳定:Binder基于C/S架构,架构简单,功能、任务分明,易用性高;
- 安全:传统IPC依赖上层协议,UID/PID由用户指定,接收方无法得到可靠的UID/PID,其次传统IPC机制接入点是开放的,恶意程序可以猜测地址获得连接,而Android系统会在App安装时为每个进程分配UID,同时Binder驱动还支持实名和匿名。
Binder底层实现原理
动态内核可加载模块机制
Linux的Loadable Kernel Module即动态内核可加载模块机制可以让具有独立功能可以被单独编译的程序,在运行时被链接到内核运行,而在Binder机制中这个负责用户进程通信的内核模块就是开篇提到的Binder驱动。
内存映射
说到内存映射就不得不提mmap(),这个mmap本质就是一个内存映射文件的函数,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。如下图所示:
mmap展开能讲的就更多了,在此就不继续深述。