文章目录
1.进程的概念
- 进程一般指一个执行单元,在pc和移动设备上指一个程序或者一个应用。
- 进程中可以包含多个线程,线程是cpu调度的最小单位。
2.Android中为什么一个APP会需要多个进程
- 分散内存占用
Android对于一个进程所占用的内存是有限制的,但是如果我们程序需要大量的内存的话,可以通过多个进程来分担 - 实现多模块
应用太大了之后肯定会有多个模块 - 一个进程退出另一个进程仍可以工作
比如子进程是推送服务,那么哪怕主进程推出了,推送服务仍然能正常工作 - 守护进程
如果我们主进程需要保活,那么可以通过守护进程去唤醒主进程
3. Android 中使用多进程的原因
- 第一种情况是一个应用因为某些原因自身需要开启多进程模式,主要的原因就是2中介绍的。
- 第二种情况是两个不同的应用之间需要进行数据交互,不同的应用本身就是两个不同的进程,因此就必须要使用进程间通信方式来达到数据交换的目的。
4.为什么要进行进程间通信
- 静态成员和单例模式完全失效:一个进程其实就相当于一个应用,一个应用对应一个虚拟机,一个虚拟机对应一块内存地址,多个进程就意味着多个虚拟机,多个内存地址,所以静态变量,单例模式肯定失效了
- 线程同步机制完全失效:不在一块内存地址,不管是锁对象还是锁全局类都无法保证线程同步,因为不同线程锁的不是一块内存。
- SharedPreferences的可靠性下降:SharePrefernces不支持两个进程同时取执行写操作,它底层是通过读写XML文件来实现的,并发写会出问题。会导致一定几率的数据丢失。
- Application会多次创建:重启一个进程,就相当于重启一个应用,重启应用,肯定创建新的Application。
5. IPC机制简介
IPC是Inter-Process Communication的缩写,含义就是跨进程通信。
- IPC(进程间通信)机制不是Android系统所独有的,其他系统也有相应的进程间通信机制。
- Android系统架构中,大量采用了Binder机制作为IPC,是Android系统中最重要的组成。
- 当然也存在部分其他的IPC方式,比如Zygote通信便是采用socket。
Android系统中,每个应用程序是由Android的Activity,Service,Broadcast,ContentProvider这四大组件的中一个或多个组合而成,这四大组件所涉及的多进程间的通信底层都是依赖于Binder IPC机制。
6. Binder的简单介绍
6.1 简介
直观的看,Binder是Android中的一个类,实现了IBinder接口
从不同角度理解Binder:
- 从IPC角度,Binder是跨进程通信方式
- 从FrameWork角度,Binder是ServiceManager连接各种Manager(如am,wm
)等的桥梁 - 从应用层角度,Binder是客户端与服务端通信的媒介

6.2 Binde相比于其他通信方式的优势
Android 系统是基于 Linux 内核的,Linux 已经提供了管道、消息队列、共享内存和 Socket 等 IPC 机制。那为什么 Android 还要提供 Binder 来实现 IPC 呢?主要是基于性能、稳定性和安全性几方面的原因。
| 优势 | 描述 |
|---|---|
| 性能 | 只需要一次数据拷贝,性能上仅次于共享内存 |
| 稳定性 | 基于C/S架构,职责明确,架构清晰,因此稳定性好 |
| 安全性 | 为每个App分配UID,进程的UID是鉴别进程身份的重要标志 |
6.3 一些重要的操作系统概念
6.3.1 Linux 中进程间通信

每个Android的进程,只能运行在自己进程所拥有的虚拟地址空间。如果是32位机,对应一个4GB的虚拟地址空间,其中3GB是用户空间,1GB是内核空间,(进程空间划分)当然内核空间的大小是可以通过参数配置调整的。对于用户空间,不同进程之间彼此是不能共享的,(进程隔离)而内核空间却是可共享的。两个用户空间的进程间通信就是通过内核空间来完成的。
通常的做法是消息发送方将要发送的数据存放在内存缓存区中,通过系统调用进入内核态。然后内核程序在内核空间分配内存,开辟一块内核缓存区,调用 copyfromuser() 函数将数据从用户空间的内存缓存区拷贝到内核空间的内核缓存区中。同样的,接收方进程在接收数据时在自己的用户空间开辟一块内存缓存区,然后内核程序调用 copytouser() 函数将数据从内核缓存区拷贝到接收进程的内存缓存区。这样数据发送方进程和数据接收方进程就完成了一次数据传输,我们称完成了一次进程间通信。
6.3.2 动态内核可加载模块 && 内存映射
跨进程通信是需要内核空间做支持的。但是 Binder 并不是 Linux 系统内核的一部分,那怎么办呢?这就得益于 Linux 的动态内核可加载模块(Loadable Kernel Module,LKM)的机制;模块是具有独立功能的程序,它可以被单独编译,但是不能独立运行。它在运行时被链接到内核作为内核的一部分运行。这样,Android 系统就可以通过动态添加一个内核模块运行在内核空间,用户进程之间通过这个内核模块作为桥梁来实现通信。
Android 系统中,这个运行在内核空间,负责各个用户进程通过 Binder 实现通信的内核模块就叫 Binder 驱动(Binder Dirver)。
Bindler是如何做到只用一次数据拷贝的呢?:内存映射
Binder IPC 机制中涉及到的内存映射通过 mmap() 来实现,mmap() 是操作系统中一种内存映射的方法。内存映射简单的讲就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间;反之内核空间对这段区域的修改也能直接反应到用户空间。
内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动。两个空间各自的修改能直接反映在映射的内存区域,从而被对方空间及时感知。也正因为如此,内存映射能够提供对进程间通信的支持。
6.4 Binder IPC 实现原理
一次完整的 Binder IPC 通信过程通常是这样:
- 首先 Binder 驱动在内核空间创建一个数据接收缓存区;
- 接着在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系;
- 发送方进程通过系统调用 copyfromuser() 将数据 copy 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。
如下图:

6.5 Binder 通信模型
一次完整的进程间通信必然包含两个进程,客户端进程(Client)和服务端进程(Server),由于进程隔离的存在,通信双方必然借助Binder来实现。
BInder是基于C/S架构的。由一系列的组件组成。包括Client,Server,ServiceManager,Binder驱动。其中Client,Server,ServiceManager运行在用户空间,Binder驱动运行在内核空间。其中 Service Manager 和 Binder 驱动由系统提供,而 Client、Server 由应用程序来实现。Client、Server 和 ServiceManager 均是通过系统调用 open、mmap 和 ioctl 来访问设备文件 /dev/binder,从而实现与 Binder 驱动的交互来间接的实现跨进程通信。

6.6 Binder 通信过程
- 首先,一个进程使用 BINDERSETCONTEXT_MGR 命令通过 Binder 驱动将自己注册成为 ServiceManager;
- Server 通过驱动向 ServiceManager 中注册 Binder(Server 中的 Binder 实体),表明可以对外提供服务。驱动为这个 Binder 创建位于内核中的实体节点以及 ServiceManager 对实体的引用,将名字以及新建的引用打包传给 ServiceManager,ServiceManger 将其填入查找表。
- Client 通过名字,在 Binder 驱动的帮助下从 ServiceManager 中获取到对 Binder 实体的引用,通过这个引用就能实现和 Server 进程的通信。
6.7 Binder 通信中的代理模式
一个问题:A 进程想要 B 进程中某个对象(object)是如何实现的呢?毕竟它们分属不同的进程,A 进程 没法直接使用 B 进程中的 object。
前面我们介绍过跨进程通信的过程都有 Binder 驱动的参与,因此在数据流经 Binder 驱动的时候驱动会对数据做一层转换。当 A 进程想要获取 B 进程中的 object 时,驱动并不会真的把 object 返回给 A,而是返回了一个跟 object 看起来一模一样的代理对象 objectProxy,这个 objectProxy 具有和 object 一摸一样的方法,但是这些方法并没有 B 进程中 object 对象那些方法的能力,这些方法只需要把把请求参数交给驱动即可。对于 A 进程来说和直接调用 object 中的方法是一样的。
当 Binder 驱动接收到 A 进程的消息后,发现这是个 objectProxy 就去查询自己维护的表单,一查发现这是 B 进程 object 的代理对象。于是就会去通知 B 进程调用 object 的方法,并要求 B 进程把返回结果发给自己。当驱动拿到 B 进程的返回结果后就会转发给 A 进程,一次通信就完成了。

本文详细介绍了Android中为何需要多进程以及进程间通信(IPC)的重要性,重点讲解了Binder IPC机制,包括Binder的基本概念、优势以及实现原理。Binder是Android系统中实现IPC的关键,相较于其他通信方式,它具有高性能、稳定性和安全性。通过Binder,应用可以实现跨进程的Service、ContentProvider等组件间的通信,并通过代理模式使得不同进程间的对象调用变得可能。

1910

被折叠的 条评论
为什么被折叠?



