在安卓系统上,我们知道每个应用都在自己的进程中运行。当应用加载时,应用程序管理器通知Zygote。Zygote分叉自身并复制虚拟机(VM)。因此,应用程序获得一个具有加载库的“热”VM。每个安卓应用都是沙盒化的,因此每个进程相互独立。沙盒概念用于管理或包含不同级别的权限,限制在每个个体应用中。因此,它需要IPC来在应用/服务/系统服务之间进行通信。在一个进程下,可能有多个线程,它们共享进程内存,但有自己的堆栈。
IPC是任何软件系统/操作系统的基础。安卓提供了两种实现IPC的方式。
上述三种方式支持设备内的IPC。让我们首先了解一下ashmem。
ashmem(匿名共享内存子系统)类似于POSIX SHM(共享内存)的概念。不同之处在于,ashmem声称克服了内存泄漏的问题。ashmem不适用于安卓应用,而是被低级别的系统软件/进程使用。系统服务器的组件,如SurfaceFlinger、AudioFlinger等,使用ashmem进行IPC。ashmem速度很快。另一个使用ashmem的例子是虚拟机,它使用ashmem提供的.oat代码。当一个进程想要与另一个进程通信时,该进程创建一个共享内存区域,然后通过Binder将该内存区域的文件描述符与它要通信的其他进程共享。这个文件描述符通过Binder发送给另一个进程。系统进程通过IMemory接口依赖ashmem,这对应用程序开发者不可见或不公开。
ashmem还进行内存管理,根据需要收缩或扩展内存区域。当系统需要更多内存时,它会缩小其区域并释放内存。如果将共享内存区域标记为固定,那么在任何情况下都不能释放该区域。ashmem使用引用计数销毁与其关联的内存区域,当引用它们的进程退出时。
基本上,ashmem是由系统级别进程使用的一种IPC方式,而不是应用程序进程。
Binder框架有着悠久的历史。最初是为Be计算机开发的,后来被Palm接管并嵌入到Palm OS中。在2005年,Binder框架以OpenBinder的名义开源(参考:OpenBinder)。Binder框架的幕后人物是由Dianne Hackborn领导的团队。在Binder领域中另一个著名的名字是George Hoffman。后来,Google聘请了这个团队来重新设计Binder框架,重新开发了Binder框架,自那时以来它就成为了安卓的一部分。
谈到Binder时,要注意你的受众是谁。通过“Binder”这个词,应用程序开发者可能会想象在框架中可用的Binder接口,以绑定到应用程序服务。另一方面,Binder的强度远不止于应用程序开发者可见的框架级别的Binder接口(IBinder)。对于应用程序开发者,有一些IPC技术可用,如Messenger、Intent、AIDL和IBinder接口本身。然而,在背后,所有这些都是基于Binder的。AOSP显示,每个都使用IBinder接口。在这里,通过“Binder”,我指的是安卓中的整个“Binder框架”。那么,我所指的这个Binder在哪里呢?
是的,Binder无处不在。上图显示了安卓系统的简要表示。有Linux内核、库、ART、框架和应用程序。每个块中都显示了一些示例内容(带箭头)。每个块中显示的蓝色框都是Binder框架的组件。Binder框架的一部分坐落在被称为Binder Driver的内核中。还有Libbinder.so,它是安卓库的一部分的Binder库。然后,在安卓框架中有IBinder接口。应用程序开发者实例化此接口以在应用程序级别进行IPC。因此,技术上,Binder贯穿整个系统栈。
在Linux系统中,有几种IPC机制可用,如文件、信号、套接字、管道,以及更高级别的D-Bus。与Android一起使用的Linux内核不包含这些强大的机制。相反,Binder替换了它们。
Binder的构建块不是确切的构建块,而是Binder的重要概念或抽象思想:
当系统启动时,Binder驱动程序允许一个进程将自身注册为上下文管理器。该进程是安卓系统的服务管理器。正如我们所知,服务管理器是所有系统服务的中央注册表。
要在两个进程之间
进行通信,应该有两个进程。一个是服务,另一个订阅它的将被称为客户端。
Binder令牌用于标识。当将Binder消息传递给其他进程时,它会携带一个标识令牌,以识别发送者。
Binder协议只是在从一个进程传递消息到另一个进程时发生的不同步骤。消息传递不能像下面这样进行:
而应该考虑以下图示:
在上图中,有两个进程A和B,A想向B发送消息(黄色框)。这两个进程应该通过IBinder接口(Intent、AIDL、IBinder、Messenger,都无关紧要)相互“绑定”。每个进程上显示的绿色椭圆是只读内存区域,从中各自的进程可以读取数据,但不能写入。只有内核可以将数据写入这些绿色椭圆。与任何其他设备驱动程序一样,Binder驱动程序还实现了ioctl()函数。进程A调用此函数将消息传递给Binder驱动程序。Binder驱动程序提供了一个名为binder_write_read的特殊结构。消息以此格式传递。
如上图所示,现在数据已经传输到内核空间。从这里,内核将数据放入通信通道的另一侧,最终进入B进程的内存区域,如下图所示:
从这里,进程B读取它以进行进一步处理。
如上所述,binder驱动程序是一个软件组件,加载在内核空间中,负责将数据从一个进程的内存区域传递到另一个进程。可以通过ioctl()调用访问它。
注意:只读内存区域在进程区域中显示。但它们实际上是由内核管理的。
Binder支持:
也许会让人惊讶,但安卓使用套接字与系统的某个组件通信。那就是Zygote。当Zygote被冷启动(通过从init.rc启动的app_process启动)时,它启动一个VM并保持一个套接字打开以侦听来自应用程序管理器的指令。当用户启动应用程序时,应用程序管理器通过此打开的套接字通知Zygote。