Binder机制是Android系统提供的一种高级IPC机制,它使用代理对象、共享内存和序列化等技术,实现了进程间通信和远程调用的功能。它允许在不同进程之间进行数据传输和方法调用,实现了进程间的解耦。在Android系统中,Binder被广泛应用于各种组件之间的通信,例如Activity与Service、Service与Service、应用与系统服务等。

Binder的概念如下:

  1. 驱动层:Binder作为一个设备驱动存在于Linux内核中。当应用程序与Binder对象进行通信时,实际上是在与Binder驱动进行交互。Binder驱动负责管理Binder对象、传输数据以及进程间的上下文切换等工作。设备文件节点通常是 /dev/binder

不过,在某些版本的Android中,您可能会看到其他设备文件节点,如 /dev/hwbinder 和 /dev/vndbinder。这些设备节点都是用于Binder驱动的不同实例,分别用于硬件抽象层(HAL)和供应商模块之间的通信。

  1. 用户空间库:Binder提供了一套C++库和Java库,以方便用户空间的应用程序使用。这些库包括序列化/反序列化数据的工具、用于管理Binder对象的引用计数的工具以及在进程间调用方法时的代理和存根对象等。在Java层,通常使用AIDL(Android Interface Definition Language)来定义跨进程接口。
  2. 代理与存根:Binder机制使用了代理(Proxy)和存根(Stub)对象来实现进程间的方法调用。当一个进程要调用另一个进程中的方法时,它会通过代理对象将方法调用转换为一个Binder事务。然后,这个事务会被发送到接收进程,由存根对象解析并执行对应的方法。最后,存根对象将结果返回给代理对象,完成整个跨进程调用。
  3. 序列化与反序列化:在进程间传输数据时,需要将数据序列化为字节流,以便在不同进程之间进行传输。在接收进程中,数据会被反序列化为原始格式。Binder提供了一套序列化和反序列化的工具(如Parcel类),用于在进程间传输数据。
  4. 引用计数与死亡通知:Binder机制通过引用计数来管理Binder对象的生命周期。当一个进程获得了另一个进程的Binder对象引用时,引用计数会增加。当引用计数减少到零时,Binder对象会被销毁。另外,Binder还支持死亡通知机制,允许一个进程监听另一个进程的Binder对象死亡事件。

实现原理

Binder IPC(进程间通信)机制在数据传输过程中使用了一种称为"引用计数的内存映射"(reference-counted memory mapping)技术。这种技术通过共享内存来减少数据在发送方和接收方之间的复制操作。

在Binder IPC传输过程中,以下步骤涉及到引用计数的内存映射技术:

  1. 发送方进程(客户端)将要传输的数据写入其本地内存。这些数据可能包括原始数据、文件描述符、Binder对象等。
  2. Binder驱动程序在发送方进程和接收方进程(服务端)之间建立一块共享内存区域。这个共享内存区域的引用计数被设置为1。
  3. 发送方进程将数据复制到共享内存区域,并将数据的内存地址和大小传递给Binder驱动程序。
  4. Binder驱动程序将共享内存区域的引用计数增加1,然后将共享内存区域的地址和大小传递给接收方进程。
  5. 接收方进程通过映射共享内存区域来访问数据。此时,共享内存区域的引用计数仍为2。
  6. 当发送方和接收方进程都不再需要这些数据时,它们分别告知Binder驱动程序。驱动程序随后将共享内存区域的引用计数减1。当引用计数降至0时,驱动程序释放共享内存区域。

通过这种引用计数的内存映射技术,Binder IPC可以将数据在进程间的复制操作降至最低,从而提高IPC性能。然而,这种方法并不适用于所有场景。在某些情况下,例如当数据量很小或者不同安全上下文之间的通信时,Binder仍然可能使用传统的数据复制方法。

ServiceManager

ServiceManager在系统启动过程中的初始化非常重要,因为它是Android系统服务管理的核心组件,需要在其他服务启动之前就准备就绪,以便随后可以注册和查找其他系统服务。

  1. Native层的ServiceManager是在Android系统启动阶段初始化的。在Android系统启动过程中,会执行一个名为init的程序,它负责启动和初始化系统中的各个组件和服务。在init程序执行过程中,会调用ServiceManager的main函数,从而启动并初始化Native层的ServiceManager。这样,ServiceManager就可以接收和处理来自其他进程的服务注册和查询请求。
  2. Java层的ServiceManager(位于Java层):它是一个Java类,提供了在Java层注册和获取系统服务的功能。它通过JNI(Java Native Interface)与Native层的ServiceManager进行通信,从而实现对系统服务的查询和注册。 当Java层的ServiceManager需要注册或查找一个系统服务时,它会通过JNI调用Native层的ServiceManager的相应方法。同样,当Native层的ServiceManager收到服务注册或查询请求时,会在其内部映射表中进行查找或添加相应的服务。

相关

  1. 为何System server请求zygote创建进程时用的是socket通讯而不是binder?
    可能是因为此处socket完全满足需求, 简单又高效, 并不是binder此时不可用. 因为servicemanager先于System server启动了
  2. 为什么Intent不能传递大数据?
  • 性能:将大量数据附加到 Intent 可能导致性能下降。Intent 对象在进程之间传递时,实际上是通过 Binder IPC 机制进行的。如果传递的数据量过大,可能会导致 Binder 传输缓冲区的填充和性能下降。
  • 限制:Binder 事务缓冲区的大小有限。根据 Android 版本和设备的不同,限制可能在 1MB 左右。如果超出这个大小限制,可能会抛出 TransactionTooLargeException 异常。
  • 解决方案: 文件, 共享内存, content provider
  1. 相对于其他linux ipc机制, binder有什么优势?
  • . 更高效的数据传输:Binder采用一次内存复制策略,而其他IPC机制如管道、消息队列等通常需要至少两次内存复制。这使得Binder在数据传输方面更加高效。
  • . 强类型:Binder基于接口定义语言(IDL),允许定义强类型的接口。这有助于确保数据在进程间传输时具有正确的类型和结构,从而减少潜在的类型错误和程序崩溃。
  • . 引用计数和生命周期管理:Binder内建了引用计数和对象生命周期管理机制。当一个Binder对象不再被任何进程引用时,它会自动被销毁。这有助于避免内存泄漏和资源浪费。
  • . 安全性:Binder提供了基于UID(User Identifier)的权限控制机制,允许对进程间通信进行访问控制。这有助于确保只有具备适当权限的进程才能访问特定的服务和资源。
  1. 结构简单,易于使用:Binder提供了一个简洁的API,使得开发者能够轻松地实现跨进程通信。在Android中,Binder机制被高度集成,使得开发者能够无缝地在应用程序中使用服务和组件。
  • . 适应性:Binder机制在Android系统中得到了广泛应用,支持跨平台和多种设备类型,具有很高的适应性。这使得Android设备和应用程序能够在各种不同场景中实现高效的进程间通信。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

Android Binder机制简述_共享内存


相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。