2. Binder节点监控
任务目标
在运行Android或通用Linux内核(已开启CONFIG_ANDROID_BINDER_IPC与CONFIG_FTRACE)的设备上,通过tracefs/ftrace捕获一次Binder事务从发送端到接收端的完整内核事件流,并据此还原事务的发起进程、目标进程、事务栈与耗时分布。
前置条件
- 内核版本 ≥ 4.14(推荐5.10+),已挂载tracefs:
mount -t tracefs nodev /sys/kernel/tracing(或使用旧路径/sys/kernel/debug/tracing) - 确认Binder跟踪点存在:
ls /sys/kernel/tracing/events/binder/binder_transaction应列出该事件目录 - 设备已root,或当前shell具有tracefs写权限
实现步骤
1. 启用Binder事件跟踪
清空旧跟踪缓冲并启用全部binder事件(共8个跟踪点,覆盖事务生命周期):
# 切换到tracefs目录
cd /sys/kernel/tracing
# 清空历史跟踪
echo > trace
# 启用binder相关全部事件
echo 1 > events/binder/enable
# 设置跟踪缓冲大小为1MB(避免丢失事件)
echo 1024 > buffer_size_kb
# 确认已启用
cat events/binder/enable # 应输出 1
2. 触发一次Binder事务
在另一个终端执行任意Binder调用(例如启动一个Activity、调用系统服务),或使用以下最小触发命令:
# 触发一次servicemanager查询(任何应用进程都会在启动时执行)
# 若设备空闲,可强制触发:
cmd notification help > /dev/null 2>&1
# 或使用service call命令直接发起一次Binder调用:
service call activity 42 s16 "test" > /dev/null 2>&1
3. 停止跟踪并导出数据
# 停止跟踪
echo 0 > events/binder/enable
# 导出跟踪日志(包含时间戳、进程名、PID、事务数据)
cat trace > /data/local/tmp/binder_trace.txt
4. 分析事务流程
导出的trace中,一次完整事务由以下事件序列构成(按时间顺序):
# 关键事件序列(示例格式,实际内容取决于内核版本)
binder_transaction: transaction=3049 dest_node=1 dest_proc=system_server dest_thread=... reply=0 flags=0x10 code=0x2a
binder_transaction_received: transaction=3049 proc=system_server thread=...
binder_transaction_alloc_buf: transaction=3049 data_size=128 offsets_size=8
binder_transaction_buffer_release: transaction=3049
binder_transaction_failed: transaction=3049 reply=0 (仅在失败时出现)
使用以下命令提取关键字段:
# 查看所有binder_transaction事件(发起端)
grep "binder_transaction:" binder_trace.txt | head -20
# 查看所有binder_transaction_received事件(接收端)
grep "binder_transaction_received:" binder_trace.txt | head -20
# 按事务ID关联收发两端
grep "transaction=3049" binder_trace.txt
验证方法
满足以下条件即判定跟踪成功:
cat events/binder/enable输出1,且trace文件非空- 跟踪日志中同时出现
binder_transaction与binder_transaction_received事件,且两者具有相同的transaction=ID - 能从日志中识别出发起进程(事件前的进程名/PID)与目标进程(
dest_proc=字段) - 若调用成功,日志中不会出现
binder_transaction_failed事件
常见问题
- events/binder目录不存在:内核未开启CONFIG_ANDROID_BINDER_IPC或CONFIG_FTRACE,需重新编译内核
- 跟踪无输出:确认触发命令确实执行了Binder调用(可用
service list验证servicemanager响应);部分设备需设置echo 0 > options/overwrite防止缓冲覆盖 - 事务ID不匹配:高并发下多个事务交错,按
transaction=字段过滤即可,不影响单次事务分析
可视化:Binder事务跟踪事件流
上图展示了通过ftrace捕获的Binder事务事件序列。实际分析时,使用grep "transaction=3049"即可将同一事务的四个事件关联起来,形成完整调用链。若在binder_transaction与binder_transaction_received之间出现binder_transaction_failed,则说明驱动层拒绝了该事务(常见原因为权限不足或节点不存在)。