在Binder驱动中,Binder结点随着进程IPC通信开始而生,随着进程IPC通信结束而亡,换句话说,Binder结点是维系IPC通信的基础,而且一个Binder结点也只能在完全无IPC通信的情况下被删除。本文将重点研究Binder结点从生到死的过程。
Binder结点作为IPC通信过程中的实体,是IPC通信的媒介。在描述一个进程中Binder信息的数据结构中,与结点相关的成员变量有:
struct binder_proc {
struct hlist_node proc_node;// list node for global binder_procs hlist
...
struct rb_root nodes;
struct rb_root refs_by_desc;
struct rb_root refs_by_node;
...
};
其中,nodes记录了当前进程创建的Binder结点。而refs_by_desc和refs_by_node都记录的是Binder结点引用的链表。nodes链表的大小反映了有多少进程在向当前进程请求服务,而结点引用链表的大小则反映了当前进程在向哪些进程请求服务。
创建Binder结点的函数是binder_new_node。在分析此函数之前,我们先分析一下Binder驱动中结点的数据结构定义:
struct binder_node {
int debug_id;
struct binder_work work;
union {
struct rb_node rb_node;
struct hlist_node dead_node;
};
struct binder_proc *proc;
struct hlist_head refs;
int internal_strong_refs;
int local_weak_refs;
int local_strong_refs;
void __user *ptr;
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;
unsigned accept_fds:1;
unsigned min_priority:8;
struct list_head async_todo;
};
下面分别解释上述各个成员变量的意义:
1. debug_id: 结点的一个数字序号标记,根据全局变量binder_last_id来维护并分配,binder_last_id是Binder驱动全局变量,且单调递增的。
2. work:一般类型为BINDER_WORK_NODE的binder_work,添加到线程上的todo链表中去处理,主要处理结点的引用计数。
3. 联合体:rb_node代表此结点在进程全局红黑树binder_procs上的一个结点。而dead_node代表红黑树binder_dead_nodes中的一个结点。根据当前结点的状态,将决定将结点加入到哪个全局链表中。
4. proc: 与结点相关联的binder_proc