在我们日常开发使用过程中,我们经常会通过Binder对象调用跨进程服务接口方法。但使用Binder调用服务的时候,有存在一些我们容易忽视的问题,下面我们就来看看有哪些问题吧。
1. 基本信息
| 宏定义 | 作用 | 默认值 | 调整建议 |
|---|---|---|---|
| BINDER_VM_SIZE | 定义每进程的 Binder 缓冲区大小,默认为 1MB - 2 页大小。 | 约 1MB | 可调整到更大值,例如 2MB。 |
| DEFAULT_MAX_BINDER_THREADS | 每进程的最大 Binder 线程数,限制线程创建,防止资源滥用。 | 15 | 根据需要调整,例如 20-30。 |
| DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION | 启用单向调用垃圾检测,防止过量调用对系统资源的影响。 | 1(启用) | 对高并发单向调用的服务可能需要关闭检测。 |
大小限制
// frameworks/native/libs/binder/ProcessState.cpp
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
作用:
BINDER_VM_SIZE定义了每个进程用于 Binder 缓冲区的虚拟内存大小。- 默认大小为 1MB 减去两页的大小(
sysconf(_SC_PAGE_SIZE)通常是 4KB 或 8KB,视架构而定)。 - 这表示,Binder 为每个进程分配的内存区域稍小于 1MB。
原因:
-
Binder 使用的内存需要页对齐。减去两页大小是为了给额外的内存管理结构留空间。
-
每个 Binder 进程的缓冲区从这块虚拟内存中分配。
线程限制
#define DEFAULT_MAX_BINDER_THREADS 15 // 15子线程
作用:
- 限制每个进程可以创建的最大 Binder 工作线程数,默认最多 15 个线程。所以加上1
- 这些线程在用户态处理来自 Binder 驱动的事务(
transaction)。
原因:
-
限制线程数是为了防止某个进程过多占用系统资源,导致性能下降。
-
默认值 15 是一个经验值,可以根据系统负载调整。
Oneway 异步
#define DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION 1
作用:
- 启用了 Binder 的单向调用(
oneway)的垃圾检测机制。 - 默认值为
1,表示启用。
背景:
- Binder 支持单向调用(
oneway),即异步请求。这种调用不会等待接收端返回结果,因此处理速度更快。 - 然而,如果存在过多的单向调用,可能会淹没接收端线程,导致性能问题。
启用的功能:
-
系统会检测某个进程是否发送了过多的单向调用。
-
如果检测到过量调用,可能会限制该进程的调用频率。
2. 常见问题
Service端频繁调用oneway回调函数
E Process seems to be sending too many oneway calls.
2024-11-29 15:18:52.969 2853-4313 IPCThreadState xxxxxxxxx W CallStack::getCurrentInternal not linked, returning null
2024-11-29 15:18:52.969 2853-4313 oneway spamming xxxxxxxxx W CallStack::logStackInternal not linked
2024-11-29 15:18:52.969 2853-4313 JavaBinder xxxxxxxxx E !!! FAILED BINDER TRANSACTION !!! (parcel size = 2xx64)
Service 在回调client端的函数,通常会使用oneway声明函数,异步调用。但是如果短时间内调用的频率过高,会出现上述的错误。解决方案:
- 如果是大数据分段传输,就需要重新选择数据传输方案。如传文件描述符,socket等
- 控制回调频率
Binder 接口请求数据过大
BInder缓冲区最大值是不到1M,所以需要考虑并发情况下,每次调用最大传输的数据大小。
Binder调用执行所在的线程
会在binder线程中执行,默认会在上述提到的16个线程中分配,所以可能是子线程也可能是主线程。
为什么选择使用Binder传输大数据?如何传输大数据?
-
为什么使用binder传输:通过binder机制传输数据,能够天然的使用到Android的权限校验机制
- Service permission的配置
-
如何传输:通过binder传递文件标识符,直接跨进程对文件进行读写
还有什么常见问题,可以评论区讨论讨论