在进行Binder debug或分析问题时,一般须要看一下当前的Binder状态信息。Kernel经过SYS系统提供了一些文件节点供咱们读取,它们位于/sys/kernel/debug/binder/,分别为:node
要理解这些Debug信息,必须Binder驱动中相关的数据结构定义。这些信息几乎涉及到驱动中全部的结构体,下面结合两者看一下信息的具体内容。首先看一下Binder驱动最基本的数据结构binder_proc。Binder_proc是用于描述Binder进程的数据结构,一个进程只有一个binder_proc,其余的结构体都会关联到这个数据结构中。也就是说,经过binder_proc能够查找到全部Binder进程相关的信息,如Binder线程,Binder引用,Binder内存等。cookie
struct binder_proc { struct hlist_node proc_node; /* hlist节点,链接到全局队列binder_procs中 */ struct rb_root threads; /* Binder线程的红黑树 */ struct rb_root nodes; /* Binder实体的红黑树 */ struct rb_root refs_by_desc; /* Binder引用的红黑树,以handle为key */ struct rb_root refs_by_node; /* Binder引用的红黑树,以node地址为key */ int pid; /* 进程PID */ struct vm_area_struct *vma; /* 进程虚拟地址空间指针 */ struct mm_struct *vma_vm_mm; /* 进程内存结构 */ struct task_struct *tsk; /* 进程task结构 */ struct files_struct *files; /* 进程file结构 */ struct hlist_node deferred_work_node; /* hlist节点,链接到全局队列binder_deferred_list中,用于处理binder退出任务 */ int deferred_work; /* Binder defer flag,包括PUT_FILES,FLUSH,RELEASE */ void *buffer; /* Binder内存内核起始地址 */ ptrdiff_t user_buffer_offset; /* Binder内存用户与内核间的地址偏移量 */ struct list_head buffers; /* Binder buffer的队列 */ struct rb_root free_buffers; /* 空闲Binder buffer的红黑树 */ struct rb_root allocated_buffers; /* 已分配Binder buffer的红黑树 */ size_t free_async_space; /* 异步传输的可用空间 */ struct page **pages; /* 物理内存页 */ size_t buffer_size; /* Binder内存映射的大小 */ uint32_t buffer_free; /* Binder内存的可用空间 */ struct list_head todo; /* Binder进程的todo队列 */ wait_queue_head_t wait; /* Binder进程的等待队列 */ struct binder_stats stats; /* Binder统计信息 */ struct list_head delivered_death; /* Binder已分发的死亡通知 */ int max_threads; /* Binder进程的最大线程数 */ int requested_threads; /* 请求的线程数 */ int requested_threads_started; /* 已启动的请求线程数 */ int ready_threads; /* 准备就绪的线程数 */ long default_priority; /* 缺省优先级 */ struct dentry *debugfs_entry; /* debugfs入口 */ };
State最开始记录的时死亡的Binder(dead node)。由于这些Binder的进程已经死掉,它们当前不属于任何进程,因此将它们记录在一个全局的队列中(binder_dead_nodes)。死亡记录展现以下,数据结构
Dead nodes相关的数据结构为binder_node,binder_node表明着binder实体。进程中的binder_node由Proc的nodes红黑树管理,死亡的binder_node由全局的hlist binder_dead_nodes管理,还有一个全局binder_context_mgr_node用来记录system_server的binder_node。其定义以下,多线程
struct binder_node { int debug_id; /* binder node在驱动里的全局id,用于调试 */ struct binder_work work; /* binder工做队列。用于增长/删除binder,更新binder引用计数 */ union { struct rb_node rb_node; /* Proc nodes红黑树的 rb_node */ struct hlist_node dead_node; /* 死亡的binder_node,当一个进程结束时,它的binder也被销毁。但若是其余进程还在引用它的binder,则binder node没法移除,成为dead node */ }; struct binder_proc *proc; /* binder node所属的进程 */ struct hlist_head refs; /* binder node引用的队列,用于遍历binder node的全部引用 */ int internal_strong_refs; /* binder node的外部强引用计数 */ int local_weak_refs; /* 驱动内部的binder弱引用计数 */ int local_strong_refs; /* 驱动内部的binder强引用计数 */ void __user *ptr; /* 用户空间指向binder的指针,用于索引 */ void __user *cookie; /* 用户空间的附加指针 */ unsigned has_strong_ref:1; /* 是否有强引用 */ unsigned pending_strong_ref:1; /* 是否有等待处理的强引用 */ unsigned has_weak_ref:1; /* 是否有弱引用 */ unsigned pending_weak_ref:1; /* 是否有等待处理的弱引用 */ unsigned has_async_transaction:1; /* 在Todo队列中是否有未完成的异步传输 */ unsigned accept_fds:1; /* 是否赞成接受文件方式的binder*/ unsigned min_priority:8; /* 设置处理Binder请求的线程的最低优先级 */ struct list_head async_todo; /* 异步传输等待队列 */ }
Dead nodes信息后面跟着是当前系统中全部的Binder进程的信息,该信息包括:进程中Binder线程的状态,Binder实体信息,Binder引用信息,binder buffer信息。异步
线程状态显示了Binder进程中全部的Binder线程的PID和线程状态,binder_thread数据结构和线程状态定义以下。async
enum { BINDER_LOOPER_STATE_REGISTERED = 0x01, /* 注册线程(BC_REGISTER_LOOPER) */ BINDER_LOOPER_STATE_ENTERED = 0x02, /* 建立主线程(BC_ENTER_LOOPER) */ BINDER_LOOPER_STATE_EXITED = 0x04, /* 已退出 */ BINDER_LOOPER_STATE_INVALID = 0x08, /* 无效 */ BINDER_LOOPER_STATE_WAITING = 0x10, /* 等待中 */ BINDER_LOOPER_STATE_NEED_RETURN = 0x20 /* 须要返回 */ }; struct binder_thread { struct binder_proc *proc; /* 线程所属的而进程 */ struct rb_node rb_node; /* 红黑树节点,插入到binder_proc->threads中 */ int pid; /* 线程PID */ int looper; /* 线程looper状态,用上面的枚举描述 */ struct binder_transaction *transaction_stack; /* Binder传输栈 */ struct list_head todo; /* Binder线程todo队列 */ uint32_t return_error; /* 写失败时的返回错误码 */ uint32_t return_error2; /* 写失败时的返回错误码2 */ wait_queue_head_t wait; /* Binder线程等待队列 */ struct binder_stats stats; /* Binder线程统计信息 */ };
而后是Binder进程中Binder实体的信息,解释参考Dead nodes。接着打印的是进程中Binder引用的信息,相关数据结构为binder_ref,用作Binder实体的代理。oop
struct binder_ref { /* Lookups needed: */ /* node + proc => ref (transaction) */ /* desc + proc => ref (transaction, inc/dec ref) */ /* node => refs + procs (proc exit) */ int debug_id; /* 全局id,用于调试 */ struct rb_node rb_node_desc; /* 红黑树节点,用于binder_proc->refs_by_desc */ struct rb_node rb_node_node; /* 红黑树节点,用于binder_proc->refs_by_node */ struct hlist_node node_entry; /* hlist节点,用于binder_node->refs索引 */ struct binder_proc *proc; /* 指向的Binder 进程 */ struct binder_node *node; /* 指向的Binder实体 */ uint32_t desc; /* handle值 */ int strong; /* 强引用 */ int weak; /* 弱引用 */ struct binder_ref_death *death; /* 已注册的死亡通知地址 */ };
最后时Binder进程中Binder buffer的信息。相关数据结构为binder_buffer,用于存储Binder传输数据。ui
struct binder_buffer { struct list_head entry; /* list节点,链接到binder_proc->buffers */ struct rb_node rb_node; /* 红黑树节点,插入到binder_proc->free_buffers(buffer空闲时)或binder_proc->allocated_buffers(buffer已分配时) */ unsigned free:1; /* 是否空闲 */ unsigned allow_user_free:1; /* 是否容许用户释放 */ unsigned async_transaction:1; /* 是否为异步传输 */ unsigned debug_id:29; /* 全局id,用于调试 */ struct binder_transaction *transaction; /* 指向的Binder传输事务 */ struct binder_node *target_node; /* 指向的Binder实体 */ size_t data_size; /* 数据大小 */ size_t offsets_size; /* 数据偏移量 */ uint8_t data[0]; /* 数据地址 */ }
Stats包含的Binder的统计信息,包括传输命令的统计,内部对象的统计等。开始输出的是所有Binder的统计信息,以后按Binder进程逐个输出统计信息。一个输出示例以下,spa
Binder统计信息经过binder_stats来表示,线程
struct binder_stats { int br[_IOC_NR(BR_FAILED_REPLY) + 1]; /* Binder 返回命令的计数 (Binder Driver Return Protocol)*/ int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1]; /* Binder 写命令的计数 (Binder Driver Command Protocol)*/ int obj_created[BINDER_STAT_COUNT]; /* Binder 内部对象的计数,建立时加1 */ int obj_deleted[BINDER_STAT_COUNT]; /* Binder 内部对象的计数,删除时加1 */ };
以BC_开头的命令为应用层向Binder驱动发送的请求命令,定义以下,
Cmd | Description | Args | Code |
---|---|---|---|
BC_TRANSACTION | Client向Server发送请求数据 | binder_transaction_data: the sent command | 10763886080x40286300 |
BC_REPLY | Server向Client发送回复(应答)数据 | binder_transaction_data: the sent command | 10763886090x40286301 |
BC_ACQUIRE_RESULT | 暂未实现 | --- | 10740293140x40046302 |
BC_FREE_BUFFER | 释放一块映射的内存。 | void *: ptr to transaction data received on a read | 10740293150x40046303 |
BC_INCREFS | 增长Binder的弱引用计数 | int: descriptor | 10740293160x40046304 |
BC_ACQUIRE | 增长Binder的强引用计数 | int: descriptor | 10740293170x40046305 |
BC_RELEASE | 减小Binder的强引用计数 | int: descriptor | 10740293180x40046306 |
BC_DECREFS | 减小Binder的弱引用计数 | int: descriptor | 10740293190x40046307 |
BC_INCREFS_DONE | Binde实体所在的进程处理完BC_INCREFS的反馈 | void : ptr to bindervoid : cookie | 10742914640x40086308 |
BC_ACQUIRE_DONE | Binde实体所在的进程处理完BC_ACQUIRE的反馈 | void : ptr to bindervoid : cookie | 10742914650x40086309 |
BC_ATTEMPT_ACQUIRE | 暂未实现 | --- | 10742914660x4008630a |
BC_REGISTER_LOOPER | 通知驱动线程池中一个线程已经建立 | --- | 253550x630b |
BC_ENTER_LOOPER | 通知驱动该线程已经进入主循环,能够接收数据 | --- | 253560x630c |
BC_EXIT_LOOPER | 通知驱动该线程退出主循环,再也不接收数据 | --- | 253570x630d |
BC_REQUEST_DEATH_NOTIFICATION | Binder引用的进程要求得到Binder的实体死亡通知 | void : ptr to bindervoid : cookie | 10742914700x4008630e |
BC_CLEAR_DEATH_NOTIFICATION | 清除得到Binder的实体死亡通知 | void : ptr to bindervoid : cookie | 10742914710x4008630f |
BC_DEAD_BINDER_DONE | 收到实体死亡通知书的进程在删除引用后用本命令告知驱动 | void *: cookie | 10740293280x40046310 |
以BR_开头的命令为Binder驱动向应用层发送的回复命令,定义以下,
Cmd | Description | Args | Code |
---|---|---|---|
BR_ERROR | 发生内部错误(如内存分配失败) | int: error code | 21477749760x80047200 |
BR_OK | 操做完成 | --- | 291850x7201 |
BR_TRANSACTION | 对应发送方的BC_TRANSACTION | binder_transaction_data: the received command | 21501342740x80287202 |
BR_REPLY | 对应发送方的BC_REPLY | binder_transaction_data: the received command | 21501342750x80287203 |
BR_ACQUIRE_RESULT | 暂未实现 | --- | 21477749800x80047204 |
BR_DEAD_REPLY | 交互过程当中若是发现对方进程或线程已经死亡则返回该消息 | --- | 291890x7205 |
BR_TRANSACTION_COMPLETE | 接收方发送该消息做为BC_TRANSACTION或BC_REPLY发送成功的反馈 | --- | 291900x7206 |
BR_INCREFS | 增长Binder本地对象的弱引用计数 | void : ptr to bindervoid : cookie for binder | 21480371270x80287207 |
BR_ACQUIRE | 增长Binder本地对象的强引用计数 | void : ptr to bindervoid : cookie for binder | 21480371280x80287208 |
BR_RELEASE | 减小Binder本地对象的强引用计数 | void : ptr to bindervoid : cookie for binder | 21480371290x80287209 |
BR_DECREFS | 减小Binder本地对象的弱引用计数 | void : ptr to bindervoid : cookie for binder | 21480371300x8028720a |
BR_ACQUIRE_RESULT | 暂未实现 | --- | 21482992750x800c720b |
BR_NOOP | 不作事情, | --- | 291960x720c |
BR_SPAWN_LOOPER | 驱动发现接收方全部线程都处于忙碌状态,向接收方发送该命令要求建立更多线程以备接收数据 | --- | 291970x720d |
BR_FINISHED | 暂未实现 | --- | 291980x720e |
BR_DEAD_BINDER | 向得到Binder引用的进程发送Binder实体死亡通知 | void **cookie | 21477749910x8004720f |
BR_CLEAR_DEATH_NOTIFICATION_DONE | 死亡通知清除完成 | void **cookie | 21477749920x80047210 |
BR_FAILED_REPLY | 若是发送非法引用号则返回该消息 | --- | 292010x7211 |
这两个文件节点提供了最近32次成功与失败的传输记录,输出信息大体相同。
相关的数据结构为binder_transaction_log_entry。这个结构体作为Binder传输的描述,每次发起Binder传输时记录到全局结构体中,用于debug。
struct binder_transaction_log_entry { int debug_id; /* transaction log ID */ int call_type; /* 传输类型,0:call, 1:async, 2:replay */ int from_proc; /* 发起传输的进程 PID*/ int from_thread; /* 发起传输的线程 PID */ int target_handle; /* Binder实体的引用, 接收时为-1 */ int to_proc; /* 处理传输的进程 PID*/ int to_thread; /* 处理传输的线程 PID,若是不存在值为0 */ int to_node; /* 处理传输的Binder node ID */ int data_size; /* 传输数据的长度 */ int offsets_size; /* 传输数据的偏移量 */ }; struct binder_transaction_log { int next; /* 传输log计数 */ int full; /* 传输log是否已满 */ struct binder_transaction_log_entry entry[32]; /* 传输log记录 */ }; static struct binder_transaction_log binder_transaction_log; static struct binder_transaction_log binder_transaction_log_failed;
Transactions中记录了当前系统中全部Binder进程的传输状态,一个输出示例以下,
这个输出信息中包含许多数据结构里的内容,buffer信息与binder_buffer相关,thread信息与binder_thread相关,还有一个最重要的传输事件是由binder_transaction来描述的。
struct binder_work { struct list_head entry; /* 工做队列节点 */ enum { BINDER_WORK_TRANSACTION = 1, BINDER_WORK_TRANSACTION_COMPLETE, BINDER_WORK_NODE, BINDER_WORK_DEAD_BINDER, BINDER_WORK_DEAD_BINDER_AND_CLEAR, BINDER_WORK_CLEAR_DEATH_NOTIFICATION, } type; }; ...... struct binder_transaction { int debug_id; /* 全局ID,用于调试 */ struct binder_work work; /* 传输的工做类型 */ struct binder_thread *from; /* 传输发送端线程 */ struct binder_transaction *from_parent; /* 发送端传输事件 */ struct binder_proc *to_proc; /* 传输接收端进程 */ struct binder_thread *to_thread; /* 传输接收端线程 */ struct binder_transaction *to_parent; /* 接收端传输事件 */ unsigned need_reply:1; /* 是否须要回复 */ /* unsigned is_dead:1; */ /* not used at the moment */ struct binder_buffer *buffer; /* 传输数据的buffer */ unsigned int code; /* 传输的命令码 */ unsigned int flags; /* 传输标识,例如TF_ONE_WAY */ long priority; /* 传输优先级 */ long saved_priority; /* 传输缺省优先级 */ kuid_t sender_euid; /* 发送端的uid */ }