当前位置: 首页 > news >正文

【Android基础回顾】一:Binder机制是什么?有什么用?

Android中的Binder机制是Android系统中最核心和最基础的进程间通讯机制。

1 什么是进程间通讯机制(IPC)?

众所周知,Android系统基于Linux开发,Linux系统里面本来就有进程间通讯机制。

1.1 Linux的IPC(Inter-Process Communication)概览

它是不同进程之间交换数据和消息的一种手段。

但是进程之间默认地址空间是隔离的,有什么解决方案去做到不同进程之间交换信息吗?答案是当然有。

下图整理自AI。

类型示例特点说明
文件系统相关管道、命名管道(FIFO)简单,适合父子进程或有命名路径的通信
内存相关共享内存高效,速度快,但需自行同步(如用信号量)
消息传递消息队列、信号、信号量安全、结构化,但效率略低
套接字通信本地 Socket、网络 Socket灵活,可跨主机,适用于客户端-服务器架构
高级通信机制DBus、ZeroMQ、gRPC、Binder等抽象层高,适合复杂或跨语言系统

对于这个列表,我们重点是需要关注这些方案的原理是什么。只有知道原理,我们才能解开现象背后的本质,对于很多技术难题,我们才能有思路举一反三。

1.2 文件系统相关(管道、命名管道 FIFO)

这类IPC本质上是一个内核缓冲区,读写操作通过文件描述符来跟缓冲区进行交互。

写端进程通过write写入缓冲区,读端进程通过read读取数据。
这种属于阻塞式通讯,读和写都需要等对方准备好,系统通过文件描述符来判断是否可以进行读和写。

1.3 内存相关(共享内存)

这类IPC,在不同进程的虚拟地址空间通过映射的方式,比如mmap来映射到一段共同的物理内存页来实现“共享”。

进程通过指针直接访问内存中的数据结果,完全绕过了内核的读写接口,所以速度极快。俗称“零拷贝”。这种机制是没有内建锁的,进程需要通过锁机制等保证并发安全。

1.4 消息传递类(消息队列、信号、信号量)

消息队列:内核维护一个消息队列结构体,发送进程通过系统调用把消息copy到内核队列中(第一次拷贝)。接收方从队列中获取信息(第二次拷贝)。

信号:信号是系统内核或者进程向另一个进程发送的异步通知,用来通知某事件的发生。这是一种轻量级的IPC方式。

核心原理是内核使用位图或者信号队列标记进程收到的信号,调度器在合适的时候调用信号处理函数。

信号量:是一种同步原语。本质上是内核中的一个整数值结构 + 等待队列,用于资源访问同步。

P/V 操作中,P(等待)将信号量值减一,若 < 0 进程阻塞;V(释放)加一,并唤醒等待队列中的进程。

1.5 套接字通信(本地 / 网络 Socket)

Linux 为每个 Socket 创建一个 socket 缓冲区结构(sk_buff),内核中维护双向队列。

本地 Socket 使用 UNIX Domain 协议族,数据在内核中传输,无需网络协议栈处理。

网络 Socket 走 TCP/IP 协议栈,数据被封包、路由、拥塞控制,完整链路层处理。

2 Android特有的IPC:Binder

2.1 Binder机制的有什么用?

Binder 是 Android 提供的一种高性能的 IPC 机制,用于实现:

  • 跨进程方法调用(如 A 应用调用系统服务中的方法)
  • 客户端-服务端架构模型
  • 安全的权限校验
  • 引用计数和生命周期管理

2.2 Binder机制为什么快?

可以先看下传统的消息传递类IPC做法。

图片来源:https://blog.csdn.net/carson_ho/article/details/73560642
在这里插入图片描述

而binder通信机制基于内核 Binder 驱动,使用内核内存映射区(Binder Buffer)做 zero-copy 通信。来看下Binder的做法。

图片来源:https://blog.csdn.net/carson_ho/article/details/73560642
来自网络

他的通讯流程是:发送进程 ->内核缓冲区(第一次拷贝) ->映射到接收进程。

2.2 Binder机制由什么组成?

Binder 是一个 C/S 模型(客户端/服务端),主要组成部分如下:

  1. ServiceManager
    系统服务注册与发现的“电话簿”,所有服务通过它注册和查找。

  2. Binder 驱动(Binder Driver)
    位于内核空间(/dev/binder),实现核心的 IPC 逻辑,如数据传输、线程调度、引用计数等。

  3. Binder 本地端(Client 端)
    通过代理类(Proxy)与服务端通信,通常由 AIDL 自动生成。

  4. Binder 服务端(Server 端)
    实现具体的业务逻辑,继承 Binder 类并重写方法。

  5. Binder线程池(Binder线程)
    服务端进程中专门处理来自 Binder 驱动的调用请求的线程(由 BinderThreadPool 管理)。

下面是一个App调用系统AMS的一个例子:

在这里插入图片描述

3 常见问题

3.1 如果超过16个进程同时在使用AIDL进行通讯,会发生什么?

首先,16 并不是硬性限制,“16个进程”来源于 Android Binder 线程池默认上限,它是一个服务端并发处理能力的限制,而不是进程数量的限制。

Android 中,服务端 Binder 对象默认最多有 16 个 Binder 线程(可通过 android.os.Binder.setThreadPoolMaxThreadCount(int) 设置)。

而这个限制影响的是,服务端一次性能并发处理的 Binder 请求线程数。

并不是说客户端数量最多 16 个,而是服务端的同时“处理线程”是 16。

那么如果超过 16 个进程同时通过 AIDL 访问一个服务,会发生什么呢?

  1. 请求不会失败,但需要排队等待,如果服务端的 16 个 Binder 线程都在处理请求,第 17 个及之后的请求将进入等待队列。

  2. 客户端 transact() 系统调用会阻塞,直到服务端有空闲线程。

  3. 服务响应变慢(可观的延迟)。随着并发请求数增加,响应时间线性上升,尤其是服务端执行耗时任务时。比如,图像处理、数据库查询等在主线程处理会导致严重卡顿。

  4. 线程池饱和后,部分请求可能被拒绝(极端情况)。如果服务端主动设置了最大等待队列长度(如基于 ThreadPoolExecutor),也可能在高负载时拒绝新请求(抛出 RejectedExecutionException)。但这取决于服务的实现方式,Binder 驱动本身仍是队列化的。

  5. 主线程阻塞风险,如果服务端是 onTransact() 或处理逻辑运行在主线程上,那么并发调用容易造成 ANR(应用无响应)。Google 明确建议服务端操作应放到 HandlerThread / BinderThreadPool / JobScheduler 等后台线程。

后续继续补充。。。

http://www.lqws.cn/news/155485.html

相关文章:

  • Kaggle-Predicting Optimal Fertilizers-(多分类+xgboost)
  • npm install 相关命令
  • 第46节:多模态分类(图像+文本)
  • 【高等数学】傅里叶级数逼近例子
  • 阿里云 Linux 搭建邮件系统全流程及常见问题解决
  • STM32中自动生成Flash地址的方法
  • 肿瘤相关巨噬细胞(TAM)
  • DeepSeek 赋能智能养老:情感陪伴机器人的温暖革新
  • Vue 中组件命名与引用
  • NoSQL 之 Redis 配置与优化
  • C++ 重载和模板
  • 美化显示LLDB调试的数据结构
  • 数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
  • 【达梦数据库】OOM问题排查思路
  • 03 Deep learning神经网络的编程基础 代价函数(Cost function)--吴恩达
  • 机器学习——什么时候使用决策树
  • Django之表格上传
  • JUnit
  • 实现单例模式的常见方式
  • 基于Java(SpringBoot、Mybatis、SpringMvc)+MySQL实现(Web)小二结账系统
  • 一、ES6-let声明变量【解刨分析最详细】
  • 华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
  • 快速用 uv 模拟发布一个 Python 依赖包到 TestPyPI 上,以及常用命令
  • 机器学习实验八--基于pca的人脸识别
  • 游戏开发中的CI/CD优化案例:知名游戏公司Gearbox使用TeamCity简化CI/CD流程
  • 深入解析CI/CD开发流程
  • Bug问题
  • Java 高频面试题场景(四):社区老年大学在线学习平台系统
  • 如何处理React中表单的双向数据绑定?
  • pg数据库表里面id值,使用sql语句赋值,唯一性