一、Binder线程池的默认线程数
每个Binder进程默认有16个线程,但这一线程池是进程级别而非对象级别的。具体规则如下:
- 线程池归属:
Binder线程池属于整个进程,所有该进程内的Binder对象共享这组线程。例如,system_server
进程默认有16个Binder线程,处理所有系统服务的请求。 - 线程池初始化:
进程启动时(如通过Zygote孵化),会在Native层创建ProcessState
对象,初始化线程池并设置默认最大线程数为16。这一参数定义在ProcessState.cpp
中(DEFAULT_MAX_BINDER_THREADS
)。 - 动态调整能力:
当线程池满负荷时,Binder驱动会通过BR_SPAWN_LOOPER
指令通知进程创建新线程,直到达到上限(默认16,可配置为更高值)。
二、Binder请求处理机制
Binder处理客户端请求的核心流程分为驱动层转发和用户层执行两个阶段:
1. 请求接收与驱动层路由
- 客户端发送请求:
客户端通过BinderProxy
对象调用transact()
,将方法标识(如TRANSACTION_test
)、参数等数据封装为Parcel
,并通过ioctl
系统调用发送到Binder驱动。 - 驱动层处理:
Binder驱动在内核中创建事务(binder_transaction_data
),将请求加入目标进程的todo
队列,并唤醒该进程的等待线程。
2. 服务端线程池处理
- 线程分配:
服务端进程的Binder线程池中,空闲线程通过IPCThreadState
从驱动读取请求(BR_TRANSACTION
指令),解析出目标Binder对象和方法标识。 - 执行事务:
调用BBinder::transact()
,最终路由到服务实现的onTransact()
方法,执行具体逻辑(如数据库操作或计算任务)。 - 结果返回:
将执行结果通过Parcel
写回内核缓冲区,驱动将数据拷贝至客户端进程的用户空间,并唤醒客户端等待线程。
3. 关键优化机制
- 零拷贝传输:
通过mmap
内存映射,数据仅需一次从客户端用户空间到内核空间的拷贝,服务端直接通过映射关系访问内核缓冲区,避免二次拷贝。 - 优先级继承:
Binder驱动将客户端线程的优先级传递给服务端处理线程,确保高优先级请求优先处理(如系统关键服务的调用)。
三、线程池瓶颈与解决方案
当线程池成为瓶颈时(如所有线程被阻塞),可能引发ANR或TransactionException
。解决方法包括:
- 优化服务逻辑:
避免在onTransact()
中执行耗时操作,改用异步回调或子线程处理。 - 调整线程池参数:
通过Binder.setMaxThreads()
动态扩展线程数上限(如IO密集型服务可设置为32)。 - 使用
oneway
调用:
对无需返回结果的操作声明为oneway
,减少线程占用时间。
总结
- 线程池归属:每个Binder进程默认16线程,共享于所有对象。
- 请求处理流程:客户端→驱动→服务端线程池→事务执行→结果返回,依赖内存映射和线程调度优化性能。
- 扩展性设计:动态线程创建、优先级继承和异步机制保障高并发场景的稳定性。