Binder 与 Handler 原理深入详解
更新: 5/15/2026 字数: 0 字 时长: 0 分钟
1. Binder 驱动层原理
1.1 Binder 通信模型
用户空间 内核空间 用户空间
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ Client │ ① transact │ │ │ Server │
│ │ ──────────────→ │ │ │ │
│ Proxy │ copy_from_user │ Binder 驱动 │ ② 唤醒 │ Stub │
│ │ │ │ ──────────→ │ │
│ │ │ 内核缓冲区 │ │ onTransact│
│ │ ④ 返回 │ (mmap 映射到 │ ③ 直接读取 │ │
│ │ ←────────────── │ Server 用户 │ ←────────── │ │
│ │ copy_to_user │ 空间) │ 无需拷贝! │ │
└──────────┘ └──────────────┘ └──────────┘关键:Server 进程通过 mmap 将内核缓冲区映射到自己的用户空间,所以 Server 读取数据时不需要 copy_to_user,实现了"一次拷贝"。
1.2 mmap 一次拷贝详解
c
// binder_mmap() - Binder 驱动中的 mmap 实现
static int binder_mmap(struct file *filp, struct vm_area_struct *vma) {
struct binder_proc *proc = filp->private_data;
// 1. 在内核虚拟地址空间分配一块区域
area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
proc->buffer = area->addr;
// 2. 分配物理页面
page = alloc_page(GFP_KERNEL);
// 3. 将物理页面同时映射到:
// a) 内核虚拟地址空间(Binder 驱动可以访问)
// b) 用户虚拟地址空间(Server 进程可以访问)
map_kernel_range_noflush(...) // 映射到内核
vm_insert_page(vma, ...) // 映射到用户空间
// 结果:内核缓冲区和 Server 用户空间指向同一块物理内存
}数据传输过程:
1. Client 调用 transact(),数据在 Client 用户空间
2. Binder 驱动调用 copy_from_user(),将数据拷贝到内核缓冲区 ← 唯一的一次拷贝
3. 由于 mmap,Server 用户空间直接映射到这块内核缓冲区
4. Server 直接读取数据,无需再次拷贝1.3 Binder 线程池
Server 进程
├── 主线程(UI 线程)
├── Binder 线程 1 ← 处理 Client A 的请求
├── Binder 线程 2 ← 处理 Client B 的请求
├── ...
└── Binder 线程 N ← 最多 15 个(默认)
// ProcessState.cpp
#define DEFAULT_MAX_BINDER_THREADS 15
// 线程池启动
void ProcessState::startThreadPool() {
spawnPooledThread(true); // 创建第一个 Binder 线程
}
void IPCThreadState::joinThreadPool(bool isMain) {
do {
// 循环读取 Binder 驱动的命令
result = getAndExecuteCommand();
// 如果线程不够用,驱动会通知创建新线程
// BR_SPAWN_LOOPER → spawnPooledThread(false)
} while (result != -ECONNREFUSED && result != -EBADF);
}1.4 AIDL 深入
oneway 关键字:
aidl
// 普通调用:同步阻塞,Client 等待 Server 返回
interface IMyService {
String getData(); // Client 线程阻塞直到 Server 返回
}
// oneway 调用:异步非阻塞,Client 不等待
oneway interface IMyCallback {
void onResult(String data); // Client 发完就返回,不等 Server 处理
}oneway 的限制:
- 不能有返回值(void)
- 不能有 out/inout 参数
- 异常不会传回 Client
in/out/inout 参数:
aidl
interface IMyService {
// in:Client → Server(默认,只传过去)
void sendData(in MyParcelable data);
// out:Server → Client(传过去的是空对象,Server 填充后传回)
void receiveData(out MyParcelable data);
// inout:双向传递(Client 传过去,Server 修改后传回)
void processData(inout MyParcelable data);
}Binder 死亡通知:
kotlin
// 监听 Server 进程死亡
val deathRecipient = IBinder.DeathRecipient {
// Server 进程死了,在这里重连
reconnectService()
}
// 注册死亡通知
serviceBinder.linkToDeath(deathRecipient, 0)
// 取消注册
serviceBinder.unlinkToDeath(deathRecipient, 0)原理:Binder 驱动维护了每个 Binder 引用的死亡通知列表。当 Server 进程退出时,驱动遍历列表,向所有注册了 DeathRecipient 的 Client 发送 BR_DEAD_BINDER 命令。
1.5 ServiceManager
ServiceManager 是 Binder 的"DNS",管理所有系统服务的注册和查找:
注册服务:
SystemServer 启动时
→ AMS.addService("activity", ams)
→ WMS.addService("window", wms)
→ PMS.addService("package", pms)
→ ... 通过 Binder 调用 ServiceManager.addService()
查找服务:
App 进程
→ ServiceManager.getService("activity")
→ 返回 AMS 的 Binder 代理对象
→ App 通过代理对象调用 AMS 的方法ServiceManager 自身的 Binder 引用是固定的(handle = 0),所有进程都知道怎么找到它。
2. Handler 机制深入
2.1 epoll 机制
MessageQueue.next() 在没有消息时会阻塞,底层使用 Linux 的 epoll 机制:
c
// Looper.cpp (Native 层)
Looper::Looper() {
mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); // 创建 eventfd
mEpollFd = epoll_create1(EPOLL_CLOEXEC); // 创建 epoll
// 监听 eventfd
epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, &eventItem);
}
// 等待消息
int Looper::pollInner(int timeoutMillis) {
// epoll_wait 阻塞,直到:
// 1. 超时(延迟消息到时间了)
// 2. eventfd 可读(有新消息写入)
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
// 被唤醒后处理事件
for (int i = 0; i < eventCount; i++) {
if (eventItems[i].data.fd == mWakeEventFd) {
awoken(); // 读取 eventfd,清除唤醒标记
}
}
}
// 唤醒
void Looper::wake() {
uint64_t inc = 1;
write(mWakeEventFd, &inc, sizeof(uint64_t)); // 向 eventfd 写入,触发 epoll_wait 返回
}2.2 同步屏障详解
java
// 插入同步屏障(target == null 的 Message)
// 这是一个 hide 方法,只有 Framework 内部使用
int postSyncBarrier() {
synchronized (this) {
Message msg = Message.obtain();
msg.markInUse();
msg.when = SystemClock.uptimeMillis();
msg.arg1 = token;
// 注意:没有设置 target!普通 Message 的 target 是 Handler
// 按时间插入队列
Message prev = null;
Message p = mMessages;
while (p != null && p.when <= msg.when) {
prev = p;
p = p.next;
}
if (prev != null) {
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
return token;
}
}
// next() 中处理同步屏障
Message next() {
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
Message msg = mMessages;
// 遇到同步屏障(target == null)
if (msg != null && msg.target == null) {
// 跳过所有同步消息,找异步消息
do {
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
// 只有异步消息能通过屏障
}
if (msg != null) {
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 取出消息
return msg;
}
}
}
}
}使用场景:ViewRootImpl 在 scheduleTraversals() 时插入同步屏障,确保 UI 绘制的异步消息优先执行:
java
// ViewRootImpl.java
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 1. 插入同步屏障
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 2. 发送异步消息(Choreographer 回调)
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
// Choreographer 内部发送的是异步消息(msg.setAsynchronous(true))
}
}
void doTraversal() {
mTraversalScheduled = false;
// 3. 移除同步屏障
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
// 4. 执行绘制
performTraversals();
}2.3 IdleHandler 详解
java
// MessageQueue.java
Message next() {
int pendingIdleHandlerCount = -1;
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// ... 取消息的逻辑 ...
// 没有消息或下一条消息还没到时间
if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
mBlocked = true;
continue; // 没有 IdleHandler,继续等待
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// 执行 IdleHandler(在 synchronized 外面,不持有锁)
for (int i = 0; i < pendingIdleHandlerCount; i++) {
IdleHandler idler = mPendingIdleHandlers[i];
boolean keep = idler.queueIdle(); // 执行回调
if (!keep) {
// 返回 false,执行一次后移除
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
pendingIdleHandlerCount = 0; // 本轮已执行,不再重复
}
}实际应用:
kotlin
// 1. 延迟初始化(首帧绘制完成后的空闲时间)
Looper.myQueue().addIdleHandler {
// 在主线程空闲时执行,不影响 UI 流畅度
Analytics.init(application)
false // 只执行一次
}
// 2. 监控主线程卡顿
Looper.myQueue().addIdleHandler {
// 每次主线程空闲时记录时间
lastIdleTime = SystemClock.uptimeMillis()
true // 保持,每次空闲都执行
}
// 3. Activity 泄漏检测(LeakCanary 的做法)
// 在 onDestroy 后添加 IdleHandler,空闲时检查 Activity 是否被回收2.4 Handler 内存泄漏完整防护
kotlin
// 方案1:静态内部类 + WeakReference(Java 传统方案)
class MyActivity : AppCompatActivity() {
private class SafeHandler(activity: MyActivity) : Handler(Looper.getMainLooper()) {
private val ref = WeakReference(activity)
override fun handleMessage(msg: Message) {
val activity = ref.get() ?: return
when (msg.what) {
MSG_UPDATE -> activity.updateUI()
}
}
}
private val handler = SafeHandler(this)
override fun onDestroy() {
super.onDestroy()
handler.removeCallbacksAndMessages(null)
}
}
// 方案2:Lifecycle 感知(推荐)
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 使用 lifecycleScope,Activity 销毁时自动取消
lifecycleScope.launch {
delay(60_000)
updateUI()
}
}
}
// 方案3:自定义 LifecycleHandler
class LifecycleHandler(
private val lifecycleOwner: LifecycleOwner,
looper: Looper = Looper.getMainLooper()
) : Handler(looper), LifecycleEventObserver {
init {
lifecycleOwner.lifecycle.addObserver(this)
}
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_DESTROY) {
removeCallbacksAndMessages(null)
lifecycleOwner.lifecycle.removeObserver(this)
}
}
}3. App 启动流程源码级分析
3.1 Zygote fork 过程
java
// ZygoteInit.java
public static void main(String[] argv) {
// 1. 预加载资源(所有 App 共享)
preload(); // 加载 Framework 类、资源、OpenGL 等
// 2. 启动 SystemServer
if (startSystemServer) {
Runnable r = forkSystemServer();
if (r != null) r.run(); // 在 SystemServer 进程中执行
}
// 3. 进入循环,等待 AMS 的 fork 请求
caller = zygoteServer.runSelectLoop(abiList);
}
// ZygoteConnection.java
Runnable processOneCommand() {
// 读取 AMS 发来的参数
Arguments args = readArgumentList();
// fork 子进程
pid = Zygote.forkAndSpecialize(uid, gid, ...);
if (pid == 0) {
// 子进程
return handleChildProc(args); // → ActivityThread.main()
} else {
// Zygote 进程
handleParentProc(pid);
return null;
}
}3.2 ActivityThread.main()
java
// ActivityThread.java
public static void main(String[] args) {
// 1. 准备主线程 Looper
Looper.prepareMainLooper();
// 2. 创建 ActivityThread 实例
ActivityThread thread = new ActivityThread();
// 3. 向 AMS 注册(Binder 调用)
thread.attach(false);
// attach 内部:
// IActivityManager mgr = ActivityManager.getService();
// mgr.attachApplication(mAppThread); // mAppThread 是 ApplicationThread(Binder 服务端)
// 4. 获取主线程 Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler(); // H 类,处理所有生命周期回调
}
// 5. 开始消息循环
Looper.loop(); // 永不返回
throw new RuntimeException("Main thread loop unexpectedly exited");
}3.3 Application 创建过程
java
// AMS 收到 attachApplication 后回调
// ActivityThread.handleBindApplication()
private void handleBindApplication(AppBindData data) {
// 1. 创建 Application 的 Context
ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
// 2. 创建 Instrumentation
mInstrumentation = new Instrumentation();
// 3. 创建 Application
Application app = data.info.makeApplication(false, mInstrumentation);
// makeApplication 内部:
// app = mActivityThread.mInstrumentation.newApplication(cl, className, appContext);
// app.attach(context); // → attachBaseContext()
// 4. 初始化所有 ContentProvider
installContentProviders(app, data.providers);
// 遍历所有 Provider,依次调用 provider.attachInfo() → onCreate()
// 5. 调用 Application.onCreate()
mInstrumentation.callApplicationOnCreate(app);
}注意顺序:attachBaseContext() → ContentProvider.onCreate() → Application.onCreate()
这就是为什么在 attachBaseContext 中不能使用 ContentProvider,而很多 SDK 利用 ContentProvider 做自动初始化(在 Application.onCreate 之前就执行了)。
