Android随笔-Binder缓冲区大小为什么远小于1M
Binder 缓冲区名义上是 1MB,但实际可用空间远小于这个数值,主要有以下几个关键原因:
一、1MB 是进程级共享资源,不是单次调用配额
┌─────────────────────────────────────────┐
│ 应用进程(用户空间) │
│ ┌─────────────────────────────────────┐ │
│ │ 1MB Binder 缓冲区 │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │线程A│ │线程B│ │线程C│ │线程D│ │ │
│ │ │事务1│ │事务2│ │事务3│ │事务4│ │ │
│ │ │50KB │ │80KB │ │30KB │ │200KB│ │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ │ │
│ │ │ │
│ │ 剩余可用:1MB - 360KB = 640KB │ │
│ │ (如果再来一个线程申请 700KB → 崩溃)│ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────┘
关键点:
- 1MB 是整个进程所有线程共享的
- 不是"每次 transact 可以用 1MB"
- 任何线程的 Binder 调用都会占用这块空间
二、内核预留和分页对齐开销
┌─────────────────────────────────────────┐
│ 1MB 物理内存分配 │
├─────────────────────────────────────────┤
│ ┌─────────────┐ │
│ │ 内核管理结构 │ ~4-8KB │
│ │ binder_proc │ │
│ │ binder_node │ │
│ └─────────────┘ │
│ ┌─────────────┐ │
│ │ 页面对齐损耗 │ ~0-4KB(按页对齐) │
│ │ (4KB/页) │ │
│ └─────────────┘ │
│ ┌─────────────┐ │
│ │ 事务头开销 │ 每个事务 ~16-32B │
│ │ (binder_transaction) │
│ └─────────────┘ │
│ ┌─────────────┐ │
│ │ 实际可用数据 │ 约 900KB - 980KB │
│ │ 缓冲区 │ (不是精确的 1MB) │
│ └─────────────┘ │
└─────────────────────────────────────────┘
三、并发事务的叠加效应
开发中容易踩坑的地方:
// 场景:Activity 启动时,系统同时有多个 Binder 调用// 1. AMS 查询 Activity 信息// 2. WMS 创建窗口// 3. 通知栏更新// 4. 输入法服务绑定// 5. 你的应用同时发起网络请求...// 这些操作可能在不同线程并发执行// 每个都占用 Binder 缓冲区的一部分时间线:
- t0: 系统服务线程A 申请 200KB → 已用 200KB
- t1: 系统服务线程B 申请 300KB → 已用 500KB
- t2
