教程技术博客文档【免费下载链接】YCBlogs技术博客笔记大汇总包括Java基础线程并发数据结构Android技术博客等等常用设计模式常见的算法网络协议知识点部分flutter笔记还包括平时开发中遇到的bug汇总当然也在工作之余收集了大量的面试题长期更新维护并且修正持续完善……开源的文件是markdown格式的转载请注明出处谢谢项目地址https://gitcode.com/gh_mirrors/yc/YCBlogs点击查看免费下载导读本文以 Android 系统最核心的跨进程通信机制 Binder 为主线从什么是 Binder的四个维度切入系统剖析 Android 为何舍弃 Linux 传统 IPC 而自研 Binder 的性能与安全考量深入讲解 Binder 驱动管理的线程池模型、ServiceManager 注册/查询机制、四大角色协作流程并结合应用进程与 SystemServer 进程间的 AMS 通信实例与仓库中 AIDL 进程间通信详细介绍 的源码级实现帮助读者真正理解bindService背后一次跨进程调用的完整旅程。01 什么是 Binder从四个维度理解 Binder 的身份Binder 一词在 Android 生态中几乎无处不在但它在不同层面有截然不同的含义。理解 Binder需要从以下四个维度分别审视1. 从类定义的角度直观来说Binder 是 Android 中的一个类它继承了IBinder接口。IBinder定义了跨进程对象的基本操作契约而Binder类则是它的具体实现。2. 从 IPC进程间通信的角度Binder 是 Android 中一种独特的跨进程通信方式。它可以被理解为一种虚拟的物理设备其设备驱动为/dev/binder。这种通信方式在 Linux 中并不存在是 Android 特有的内核级通信通道。3. 从 Android Framework 的角度Binder 是ServiceManager连接各种 Manager如ActivityManager、WindowManager等和相应 ManagerService 的桥梁。系统服务如 AMS、WMS正是通过这条桥梁向应用层暴露能力的。4. 从 Android 应用层的角度Binder 是客户端和服务端进行通信的媒介。当你执行bindService时服务端会返回一个包含了服务端业务调用的 Binder 对象通过这个 Binder 对象客户端就可以获取服务端提供的服务或数据。这里的服务包括普通服务和基于 AIDL 的服务——后者正是仓库中 AIDL 基础介绍 所描述的面向对象 IPC 方案。从源码结构看AIDL 接口编译后生成的Stub类本质上就是一个 Binder 类它内部持有客户端代理Proxy两者共同构成了 Binder 通信的应用层载体详见 AIDL 进程间通信详细介绍 第 5 节的源码解析部分。02 为什么要使用 Binder性能与安全的双重考量在传统的 Linux 系统上实现进程间通信的手段并不匮乏管道Pipe、System V 消息队列、共享内存、Socket 等早已成熟。那么 Android 为什么没有直接沿用这些方案而是投入成本开发一套全新的 Binder 机制最简洁的回答只有两点性能——相比传统 Socket 更高效安全——安全性高支持通信双方进行身份验证。展开来看主要源于以下考量。2.1 传统 IPC 方案的效率缺陷跨进程通信中只有 Socket 天然支持 Client-Server 通信模式但 Socket 作为一款通用接口其传输效率低、开销大主要适合跨网络的进程间通信和本机进程间的低速通信场景。消息队列和管道采用存储-转发方式数据先从发送方缓冲区拷贝到内核开辟的缓冲区然后再从内核缓冲区拷贝到接收方缓冲区至少经历两次拷贝。在移动设备这种性能受限、需要省电的场景下广泛使用跨进程通信对通信机制的性能要求极为苛刻两次拷贝的代价难以接受。共享内存虽然一次内存拷贝都不需要但它的控制逻辑复杂难以使用同样不适合作为系统级的通用 IPC 方案。2.2 Binder 的性能优势只需一次拷贝Binder 的传输过程只需要一次内存拷贝这使其在性能上显著优于管道、消息队列和 Socket。数据拷贝次数的对比如下通信方式数据拷贝次数备注Binder1 次Android 自研兼顾性能与易用性管道 / 消息队列2 次存储-转发模式Socket2 次通用接口开销大共享内存0 次无需拷贝但控制复杂2.3 Binder 的安全优势内核级身份验证传统 IPC 在安全性上有两个致命短板无法可靠获取对方身份传统 IPC 的接收方无法获得对方进程可靠的 UID 和 PID用户 ID 和进程 ID从而无法鉴别对方身份。Android 为每个安装好的应用程序分配了独立的 UID因此 UID 是鉴别进程身份的重要标志。使用传统 IPC 时UID/PID 只能由用户在数据包中手工填入很容易被伪造被恶意程序利用。可靠的身份标记必须由 IPC 机制本身在内核中添加——这正是 Binder 驱动所擅长的。接入点完全开放传统 IPC 的访问接入点是开放的无法建立私有通道。例如命名管道的名称、System V 的键值、Socket 的 IP 地址或文件名都是公开的任何知道这些接入点的程序都可以与对端建立连接无法阻止恶意程序通过猜测接收方地址获得连接。基于以上原因Android 需要建立一套全新的 IPC 机制来满足系统对通信方式、传输性能和安全性的综合要求这就是 Binder。Binder 基于 Client-Server 通信模式传输过程只需一次拷贝为发送方自动添加 UID/PID 身份标记既支持实名 Binder 也支持匿名 Binder安全性高。2.4 额外的收益面向对象的调用方式Binder 还带来一个体验上的好处它天然支持面向对象的调用方式。使用 Binder 时跨进程调用一个远端对象的方法就如同调用本地实例一样自然。这一点在应用层体现得尤为明显——客户端拿到IBinder后通过Stub.asInterface()转换就能像调用本地接口一样调用服务端方法底层复杂的跨进程细节全部由框架与驱动屏蔽。03 Binder 如何进行线程管理驱动统一调度一个需要开发者深入了解的细节是Binder 服务端进程的线程是如何创建与管理的每个 Binder 的 Server 进程会创建很多线程来处理 Binder 请求可以简单理解为创建了一个Binder 线程池虽然实际上的管理方式并不完全等价于普通线程池。关键在于真正管理这些线程的并不是 Server 端进程而是 Binder 驱动。驱动层面对线程数量有着硬性约束一个进程的 Binder 线程数默认最大是 16超过这个数量的请求会被阻塞等待空闲的 Binder 线程出现后再继续执行。理解这一点对做进程间通信时的并发问题就能做到心中有数。例如使用 ContentProvider又一个基于 Binder 机制的组件详见 ContentProvider 分析时就能明确知道它的 CRUD创建、检索、更新和删除方法最多只能同时有 16 个线程在跑超出部分必须排队等待。这个约束在 AIDL 场景下同样成立AIDL 服务端Stub中实现的方法运行在 Binder 线程池中详见 AIDL 进程间通信详细介绍 的源码注释因此服务端实现应采用同步方式编写因为它本身已经运行在独立线程中不需要额外开线程。小结Binder 到底讲的是什么通常意义上Binder 指的就是 Android 的通信机制但从不同主体来看对于服务端进程来说Binder 指的是Binder 本地对象对于客户端进程来说Binder 指的是Binder 代理对象对于传输过程来说Binder 是可以跨进程传递的对象。04 Binder 的工作流程一次跨进程调用的完整旅程Binder 的工作流程可以拆解为以下五个步骤获取代理对象客户端首先获取服务器端的代理对象。所谓的代理对象实际上是在客户端建立一个服务端的引用该代理对象具备服务端的功能使客户端访问服务端方法就像访问本地方法一样。发送请求客户端通过调用服务器代理对象的方式向服务器端发送请求。驱动转发代理对象将用户请求通过 Binder 驱动发送到服务器进程。服务端处理并返回服务器进程处理用户请求并通过 Binder 驱动将处理结果返回给客户端的服务器代理对象。客户端接收结果客户端收到服务端的返回结果。值得注意的是应用层这一像调用本地方法的体验正是由 AIDL 生成的Stub与其内部Proxy类协作实现的当服务端和客户端位于同一进程时方法调用不会走跨进程的transact过程当两者处于不同进程时方法调用才走transact过程这个逻辑由Stub的内部代理类Proxy完成见 AIDL 进程间通信详细介绍 5.1 节对生成 Java 文件的分析。Binder 主要能提供哪些功能用驱动程序来推进进程间的通信通过共享内存来提高性能为进程请求分配每个进程的线程池针对系统中的对象引入引用计数和跨进程的对象引用映射支持进程间同步调用。05 Binder 通信机制原理ServiceManager 与代理对象的秘密Binder 通信机制的核心原理可以概括为注册 — 查询 — 代理转发三段式其运转依赖ServiceManager这个系统级中枢。第一步Server 进程向 ServiceManager 注册。Server 进程告诉 ServiceManager我是谁、我有什么、我能做什么。此时一张名字 → Binder 实体的映射关系表便生成了。第二步Client 进程向 ServiceManager 查询。Client 进程发起查询我要调用 Server 进程某个对象的方法。这个查询过程要经过 Binder 驱动此时 Binder 驱动开始发挥它的关键作用。第三步驱动返回代理对象而非实体。当向 ServiceManager 查询完毕Binder 驱动是否直接把 Server 的真实对象返回给 Client 进程其实不然。Binder 驱动将 Server 的真实对象转换成了Proxy 代理对象并转发给 Client 进程。因此 Client 进程拿到的并不是真实对象而是一个代理对象。第四步代理对象的方法调用。代理对象拥有与原对象同名的方法否则就无法欺骗Client 了但这个同名方法只是对参数进行一些包装。当 Client 进程调用这个方法时消息被发送给 Binder 驱动驱动发现调用方持有的是代理对象便通知 Server 进程调用你那个真实对象的对应方法把结果给我。Server 进程将计算结果发送给驱动驱动再转发给 Client 进程。此时 Client 进程还蒙在鼓里——它以为自己调用的是真实对象的方法其实只是调用了代理对象。不过 Client 最终拿到了计算结果目的达成。用 AIDL 案例印证代理机制仓库中 AIDL 进程间通信详细介绍 从源码层面印证了这套代理机制客户端在onServiceConnected中通过ICheckAppInfoManager.Stub.asInterface(service)将服务端返回的IBinder对象转换成 AIDL 接口对象asInterface()是区分进程的同一进程时返回Stub本身不同进程时返回Stub.proxy代理对象AIDL 生成的 Java 文件为每个接口方法声明了独立的id标识用于在transact过程中标识客户端请求的到底是哪个方法。这套机制与上文的 computer/computerProxy 类比完全同构Stub 对应 Binder 本地对象Proxy 对应 Binder 代理对象Binder 驱动负责两者间的中转。06 Binder 运行机制四大角色与互联网类比Binder 基于 Client-Server 通信模式除 Client 端和 Server 端外还有两个角色共同合作完成进程间通信功能。Binder 通信的四个角色如下角色职责说明Client 进程使用服务的进程Server 进程提供服务的进程ServiceManager 进程将字符形式的 Binder 名字转化为 Client 中对 Binder 的引用使 Client 能够通过 Binder 名字获得对 Server 中 Binder 实体的引用Binder 驱动负责进程之间 Binder 通信的建立、Binder 在进程之间的传递、Binder 引用计数管理、数据包在进程之间的传递和交互等一系列底层支持初次接触这些概念会觉得难以理解可以把四个角色和熟悉的互联网进行类比Server是服务器Client是客户终端ServiceManager是域名服务器DNSBinder 驱动是路由器。类比之下整个体系就清晰了Client 像访问网站一样按名字找到服务DNSServiceManager负责把名字解析成地址路由器Binder 驱动负责数据包在两端之间的可靠送达。07 实战案例AMS 的 Binder 通信剖析我们知道应用进程与 SystemServer 进程属于两个不同的进程进程之间需要通信。以系统中最典型的AMSActivityManagerService通信为例可以完整看到 Binder 在真实系统服务中的落位。AMS 通信的类结构Android 系统采用了自身设计的 Binder 机制其中ActivityManagerProxy和ActivityManagerNative都继承自IActivityManager而 SystemServer 进程中的ActivityManagerService对象则继承自ActivityManagerNative。简单的层级表示为Binder 接口 (IActivityManager) ├── ActivityManagerNativeBinder 本地对象基类实现 Binder 通信骨架 │ └── ActivityManagerServiceSystemServer 中的真实服务实体 └── ActivityManagerProxy客户端持有的 Binder 代理对象这样划分角色后ActivityManagerNative与ActivityManagerProxy相当于一个Binder 的客户端ActivityManagerService相当于Binder 的服务端当ActivityManagerNative调用接口方法的时候底层通过 Binder 驱动将请求数据与请求传递给 Server 端并在 Server 端执行具体的接口逻辑。这与 第 05 节 阐述的本地对象 代理对象模型完全一致AMS 就是这套模型在系统级服务上的真实投影。值得注意Binder 机制的单向性需要注意的是Binder 机制是单向的、异步的只能通过 Client 端向 Server 端传递数据与请求且调用方无需等待服务端的返回也无法直接返回。那么问题来了如果 SystemServer 进程想向应用进程传递数据怎么办答案是需要重新定义一个 Binder 请求——以 SystemServer 为 Client 端、以应用进程为 Server 端从而在两个进程之间实现双向通信。这一点在 AIDL 开发中同样常见客户端通过Message.replyTo携带自己的Messenger给服务端就是为服务端主动回调客户端搭建反向通道详见 IPC 通信方式介绍 中 Messenger 的完整代码示例。08 延伸基于 Binder 的 IPC 家族与工程实践要点理解了 Binder 机制本身之后再回头看 Android 提供的各类 IPC 方案就会豁然开朗——它们大多只是 Binder 在不同抽象层次上的封装IPC 方案与 Binder 的关系Messenger轻量级 IPC 方案底层实现是 AIDL即 Binder以串行方式处理消息无需考虑线程同步AIDL直接暴露 Binder 接口支持并发和跨进程调用方法是 Messenger 的完整版ContentProvider底层采用 Binder 机制用于跨应用数据共享Intent / 文件 / Socket非 Binder 路线各有适用场景其中 AIDL 是与 Binder 机制结合最紧密、最能体现其原理的开发形态几个工程要点值得掌握完整案例见 AIDL 进程间通信详细介绍1. 服务端与客户端的分工服务端在Service.onBind()中返回Stub实例即 Binder 本地对象客户端绑定服务后通过Stub.asInterface(service)拿到代理对象同一进程返回 Stub 本身跨进程返回 Proxy。2. 处理 Binder 意外死亡Binder 是会意外死亡的。如果服务端进程异常终止会导致远程调用失败。Android 提供了linkToDeath和unlinkToDeath两个配对方法通过linkToDeath给 Binder 设置死亡代理当 Binder 死亡时收到binderDied()通知在回调中清理引用并重新绑定服务。3. 服务端权限校验可以在清单文件中声明自定义权限并在onBind()中通过checkCallingOrSelfPermission()校验调用方权限不满足则返回 null 拒绝服务进一步提升安全性。4. 耗时操作与 ANR 风险客户端调用远程方法时会挂起等待服务端返回远程调用是耗时的因此不应在 UI 线程发起耗时远程调用而服务端Stub方法运行在 Binder 线程池中应采用同步方式实现。结语Binder 作为 Android 系统的通信底座支撑着 AMS、WMS、ContentProvider、AIDL、Messenger 等几乎所有跨进程场景。理解它的设计动机一次拷贝的性能、内核级 UID/PID 的安全、线程模型驱动管理的 16 线程池、工作流程代理对象 驱动转发与四大角色Client、Server、ServiceManager、驱动就能在开发中准确预判 IPC 的并发上限、阻塞风险与安全边界。本文的配套资料还包括 IPC 通信方式介绍六种 IPC 方案对比与完整代码、IPC 之序列化Parcelable 序列化细节、IPC 之线程进程进程与线程模型等可继续深入阅读。赞分享教程技术博客文档【免费下载链接】YCBlogs技术博客笔记大汇总包括Java基础线程并发数据结构Android技术博客等等常用设计模式常见的算法网络协议知识点部分flutter笔记还包括平时开发中遇到的bug汇总当然也在工作之余收集了大量的面试题长期更新维护并且修正持续完善……开源的文件是markdown格式的转载请注明出处谢谢项目地址https://gitcode.com/gh_mirrors/yc/YCBlogs点击查看免费下载相关推荐Android开源项目分析深度探索揭秘Binder进程通信机制的实现原理Android开源项目分析深度探索揭秘Binder进程通信机制的实现原理 Binder是Android系统中最重要的进程间通信机制它为Android四大组件文档教程技术博客RQAlpha事件驱动机制深度解析从核心原理到实战应用RQAlpha事件驱动机制深度解析从核心原理到实战应用 RQAlpha作为一款基于Python的开源量化交易框架其强大的事件驱动机制是实现高效回测和交易的核金融科技为什么选择Indigo探索Scala函数式游戏开发的终极优势为什么选择Indigo探索Scala函数式游戏开发的终极优势 Indigo是一个基于Scala的函数式游戏引擎它将函数式编程的优雅与游戏开发的创造力完美结合上一篇容器安全基线检查nerdctl配置合规性自动化工具下一篇容器镜像签名验证终极指南从手动审批到自动化安全工作流创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?