【kernel】binder死亡代理
Binder 死亡通知触发与处理时序图
┌─────────────────────────┐ ┌──────────────────────────────┐
│ 当前进程(死亡触发方) │ │ 目标进程(监听 DeathRecipient) │
└──────────┬──────────────┘ └─────────────────┬────────────┘│ 释放 Binder Node(node 所在进程死亡)││ binder_node_release()│ 遍历 node->refs 列表│ 找到注册了 death 的 binder_ref│────────────────────────────────────────►││ ref->death->work.type = BINDER_WORK_DEAD_BINDER│ binder_enqueue_work_ilocked(&ref->death->work, &ref->proc->todo)│────────────────────────────────────────► // 把任务放到目标进程 proc->todo││ binder_wakeup_proc_ilocked(ref->proc)│ └── binder_select_thread_ilocked()│ 挑一个正在等待的 binder_thread(waiting_threads)│ └── binder_wakeup_thread_ilocked()│ → wake_up_interruptible(&thread->wait)│────────────────────────────────────────► // 唤醒目标进程的 binder 线程│ 【唤醒】binder_wait_for_work() 返回││ binder_thread_read()│ 检查 thread->todo / proc->todo│ 取出刚刚 enqueue 的 work│ switch(w->type):│ case BINDER_WORK_DEAD_BINDER:│ cmd = BR_DEAD_BINDER│ put_user(cmd, ...)│ put_user(cookie, ...)│└───────────────────────────────────►用户空间(libbinder)读出 BR_DEAD_BINDER调用 DeathRecipient.binderDied()
用代码位置标注
对应你提供的 binder.c
代码:
-
投递死亡事件
binder_node_release()
ref->death->work.type = BINDER_WORK_DEAD_BINDER; binder_enqueue_work_ilocked(&ref->death->work, &ref->proc->todo); binder_wakeup_proc_ilocked(ref->proc);
-
选择线程并唤醒
binder_wakeup_proc_ilocked()
thread = binder_select_thread_ilocked(proc); binder_wakeup_thread_ilocked(proc, thread, false);
binder_wakeup_thread_ilocked()
wake_up_interruptible(&thread->wait);
-
等待工作的阻塞点
binder_thread_read()
调用if (!non_block) binder_wait_for_work(thread, wait_for_proc_work);
binder_wait_for_work()
内部:prepare_to_wait(&thread->wait, ...); schedule(); // 线程阻塞在这里,直到 wake_up_interruptible
-
醒来后处理死亡事件
binder_thread_read()
中:case BINDER_WORK_DEAD_BINDER:cmd = BR_DEAD_BINDER;put_user(cmd, ...);put_user(cookie, ...);
-
用户空间回调
- libbinder 收到
BR_DEAD_BINDER
,调用 Java 层DeathRecipient.binderDied()
。
- libbinder 收到
✅ 这样你能看到整个事件链路:
- binder_node_release 负责产生事件
- binder_wakeup_proc_ilocked 找到线程 & 唤醒它
- binder_wait_for_work 是阻塞等待的位置
- binder_thread_read 具体取出 work 并返回给用户态
- 最后用户态触发回调
如果你愿意,我还能帮你画一个 带函数调用栈 的时序链,把每个函数的调用顺序和所属文件/行号都标出来,这样你在调试内核时可以直接跟代码跳转。你要看这种更细的版本吗?