Android中应用进程中Binder创建机制
一、Zygote Fork 与 Binder 线程池创建机制
1. Zygote Fork 子进程时传递了什么?
继承资源:
/dev/binder
设备文件的文件描述符 (FD):这是进程进行 Binder IPC 的底层通道(由 Linux 内核的 Binder 驱动提供)。预加载的 Binder 相关库:如
libbinder.so
(包含ProcessState
、IPCThreadState
等关键类)。
未继承的资源:
Binder 线程池本身:Zygote 自身的 Binder 线程池 不会 被复制到子进程。
活跃的 Binder 线程:子进程启动时没有现成的 Binder 线程。
2. Binder 线程池何时创建?
首次 Binder IPC 请求触发创建!
当子进程(应用进程)第一次收到或发起 Binder 调用时,系统会动态初始化 Binder 线程池:
3. 关键代码流程(Native层)
步骤 | 关键类/方法 | 说明 |
---|---|---|
1. 应用进程启动 | App_main.cpp: main() | 进程入口,调用AndroidRuntime |
2. 初始化JVM | AndroidRuntime::start() | 启动Java虚拟机 |
3. 初始化Binder基础 | ProcessState::self()->startThreadPool() | 创建Binder主线程,但此时线程池尚未扩展 |
4. 首次收到Binder调用 | IPCThreadState::joinThreadPool() | 线程进入Binder循环 |
5. 驱动命令触发线程创建 | IPCThreadState::executeCommand(BR_SPAWN_LOOPER) | 收到BR_SPAWN_LOOPER后,创建新Binder线程 |
6. 新线程加入线程池 | ProcessState::spawnPooledThread(true) | 线程池扩展至默认上限(16线程) |
二、 ApplicationThread 如何与 Binder 线程池关联?
创建时机:
ActivityThread
在attach()
方法中创建ApplicationThread
实例:final ApplicationThread mAppThread = new ApplicationThread();
注册到AMS:
ActivityManager.getService().attachApplication(mAppThread)
将ApplicationThread
的 Binder 对象传递给 AMS。IPC 请求处理:
当 AMS 调用ApplicationThread.scheduleLaunchActivity()
时:执行线程:Binder 驱动从应用进程的 Binder 线程池中随机选择一个空闲线程处理该调用。
线程切换:此时代码运行在 Binder 线程(非主线程),需通过
mH
(Handler) 将消息转发到主线程。
三、总结
Q:Zygote fork 子进程时会创建 Binder 线程池吗?ApplicationThread 在哪个线程运行?
A:
Zygote fork 时 不创建 Binder 线程池:
子进程继承的是 Binder 通信的底层能力(如
/dev/binder
的文件描述符和预加载的库)。真正的 Binder 线程池是在首次收到 Binder IPC 请求时动态创建的(由 Binder 驱动发送
BR_SPAWN_LOOPER
命令触发)。ApplicationThread 的运行线程:
它是
ActivityThread
的内部 Binder 对象。实际执行代码在 Binder 线程池的随机线程中(非主线程),通过 Handler 将任务转发到主线程执行。
设计意义:
懒加载优化:避免进程启动时立即创建16个线程浪费资源。
动态扩展:根据 IPC 压力自动增减线程(上限16个)。
线程隔离:确保系统服务调用不阻塞主线程。
ApplicationThread 在 Binder 线程池中运行吗?
需要区分对象和执行上下文:
ApplicationThread
对象本身是ActivityThread
的成员,存在于 Java 堆中,不属于特定线程。但它的 Binder 接口方法(如
scheduleLaunchActivity
)在被 AMS 调用时:
由系统从 Binder 线程池中动态分配一个空闲线程执行
该线程负责解析 IPC 数据并转发任务到主线程
四、核心机制对比表
阶段 | Binder线程池状态 | 关键事件 |
---|---|---|
Zygote fork 完成时 | 未创建 | 仅持有 /dev/binder FD |
进程首次接收IPC请求 | 创建主线程 | 收到 BR_SPAWN_LOOPER 命令 |
后续IPC请求增多 | 动态创建新线程(≤16个) | 由Binder驱动自动调度 |
ApplicationThread调用 | 由Binder线程池的线程执行 | 通过Handler转发到主线程 |