Skip to content

Tracing Binder调用

基于 Binder tracepoint、atrace 类别和事务生命周期,建立发送、接收、分配、回复与释放的延迟分析方法。

基于android-17.0.0_r1
AndroidBinderPerfetto调试

Tracing Binder调用 ​

Binder trace 的阅读顺序是“事件字段 → 时间段 → 调度/内存关联”,不是把 tracepoint 列表当成结论。下面的时序图展示一次事务从发出到 reply/失败的采集窗口。

本文承接 binder_transaction_log、Binder死锁排查 和 Binder性能优化。trace 与 debugfs 的区别是:debugfs 给当前快照,tracepoint 给带时间顺序的事件。本文基于 Android 17 binder_trace.h 和 atrace Binder 类别,说明如何从同一个 debug id 还原事务生命周期并定位延迟。

1. 事件类别 ​

源码文件:kernel/common/drivers/android/binder_trace.h

核心事件包括 binder_transaction、binder_transaction_received、binder_transaction_alloc_buf、binder_transaction_buffer_release、binder_command、binder_return、binder_wait_for_work、binder_set_priority 和 binder_txn_latency_free。每个事件由驱动在对应状态变化处调用,未启用 trace 时不会产生可见样本。

2. 事务主线 ​

binder_transaction 记录 debug id、目标 node/proc/thread、是否 reply、code 和 flags;binder_transaction_received 表示目标线程从 work queue 取到事务。两者之间的时间包含排队和调度等待,而不是服务方法执行时间本身。

binder_transaction_alloc_buf 到 binder_transaction_buffer_release 覆盖目标 buffer 分配、交付后的持有和释放,可用来判断内存/Parcel 生命周期是否拖慢后续事务。

3. 命令往返 ​

binder_command 记录写入驱动的 BC 命令,binder_return 记录返回用户态的 BR 命令。与 Native BC_TRANSACTION/BR_TRANSACTION、BC_REPLY/BR_REPLY 对齐后,可以判断调用线程是在写入、等待、接收 reply,还是处理其他 Binder work。

4. Atrace入口 ​

源码文件:frameworks/native/cmds/atrace/atrace.cpp

binder_driver 类别要求启用 events/binder/binder_transaction、binder_transaction_received、binder_transaction_alloc_buf,可选 binder_set_priority;binder_lock 类别可启用 global lock/locked/unlock 事件。使用 atrace 或 Perfetto 选择类别,本质上是写 tracefs event enable 文件并收集这些内核事件。

5. 调度关联 ​

事务 trace 只告诉你 Binder 事件时间点;要解释中间空洞,需要同时收集 sched/sched_switch、线程唤醒和服务方法的用户态 trace。binder_set_priority 可显示继承调度策略变化;binder_wait_for_work 显示线程进入等待。没有 sched 轨迹时,不能把 alloc→received 间隔直接归因于 Binder 锁。

6. 端到端延迟 ​

对一次同步事务,可按顺序拼接:发送方 binder_transaction、目标 binder_transaction_received、服务线程用户态执行、reply 事务事件、调用方收到 BR_REPLY、buffer release。若只有 kernel 事件,服务方法内部耗时不可见;应在 AIDL/Native service 入口增加 trace section 或使用现有 Perfetto track。

7. 内存诊断 ​

binder_transaction_alloc_buf 的 data/offset/extra size 能与 Parcel size、allocator debugfs 最大连续块对照。alloc→received 很快但 release 很晚,可能是服务/客户端持有 Parcel 或 fd/blob 生命周期过长;alloc 本身慢则联读 binder_update_page_range 和 alloc mutex/页事件。

8. 锁诊断 ​

binder_lock 事件可观察全局 Binder 锁竞争,但 Android 17 主要事务状态还由 proc/node/inner 自旋锁和 allocator mutex保护。锁事件缺失时,使用 tracepoint 时间、线程栈和 debugfs 队列判断;不要把 binder_lock 类别当作所有 Binder 锁的完整覆盖。

9. 失败事务 ​

binder_netlink_report 和 binder_txn_latency_free 可补充失败/延迟释放信息;transaction log 的 return_error_line 与 trace debug id 对齐后,可区分 ENOSPC、EPERM、坏对象和目标死亡。失败事件没有业务异常堆栈,必须回到服务日志/AVC/Parcel 错误。

10. schd-dbg样本 ​

源码文件:frameworks/native/libs/binder/tests/schd-dbg.cpp

测试工具要求先用 atrace --async_start sched freq 开启调度追踪,再以 -trace 检测超 deadline 的 Binder 事务,停止 tracing 并保存 /sys/kernel/debug/trace。它展示了 Binder 事务时长必须和 sched/freq 共同解释,而不是只看 IPC 事件。

11. 采集方法 ​

先选择 binder_driver、sched、freq 和目标用户态 trace;复现短窗口;用 debug id、pid/tid、code、flags 对齐事件;再比较 alloc→received、received→reply、reply→release 三段耗时。高频场景应限制 buffer,避免 trace 本身改变调度和内存行为。

12. 阅读检查 ​

给定一条 alloc→received 很慢、一条 received→reply 很慢、一条 release 很慢的 trace,分别指出更可能是 allocator/调度排队、服务方法/下游调用、Parcel/fd 生命周期哪一层,并列出需要补采的事件或线程栈。