static int binder_open(struct inode *nodp, struct file *filp)
{
struct binder_proc *proc;
. . . . . .
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
get_task_struct(current);
proc->tsk = current;
. . . . . .
hlist_add_head(&proc->proc_node, &binder_procs);
proc->pid = current->group_leader->pid;
. . . . . .
filp->private_data = proc;
. . . . . .
}
每当进程打开/dev/binder时,binder驱动就会为其创建binder_proc结构体。
struct binder_proc
{
struct hlist_node proc_node;
struct rb_root threads;
struct rb_root nodes;
struct rb_root refs_by_desc;
struct rb_root refs_by_node;
int pid;
. . . . . .
. . . . . .
};
struct binder_node {
int debug_id;
struct binder_work work;
union {
struct rb_node rb_node; // 如果这个Binder实体还在使用,则将该节点链接到proc->nodes中。
struct hlist_node dead_node; // 如果这个Binder实体所属的进程已经销毁,而这个Binder实体又被其它进程所引用,则这个Binder实体通过dead_node进入到一个哈希表中去存放
};
struct binder_proc *proc; // 该binder实体所属的Binder进程
struct hlist_head refs; // 该Binder实体的所有Binder引用所组成的链表
int internal_strong_refs;
int local_weak_refs;
int local_strong_refs;
void __user *ptr; // Binder实体在用户空间的地址(为Binder实体对应的Server在用户空间的本地Binder的引用)
void __user *cookie; // Binder实体在用户空间的其他数据(为Binder实体对应的Server在用户空间的本地Binder自身)
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;
};
struct binder_ref {
int debug_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; // 关联到binder_node->refs哈希表中
struct binder_proc *proc; // 该Binder引用所属的Binder进程
struct binder_node *node; // 该Binder引用对应的Binder实体
uint32_t desc; // 描述
int strong;
int weak;
struct binder_ref_death *death;
};
大致通信过程:
具体过程如下:
进程1的BpBinder发起跨进程调用,向binder驱动传入自己记录的句柄值,binder驱动就会在进程1对应的binder_proc结构的引用树种查找和句柄值相等的binder_ref节点,一旦找到binder_ref节点,就可以通过该节点的node域找到对应的binder_node节点,这个目标binder_node是从属进程2的binder_proc,因为binder_ref和binder_node都处于binder驱动的地址空间中,所以是可以用指针直接指向的。目标binder_node节点的cookie域,记录的其实是进程2中BBinder的地址,binder驱动只需把这个值反映给应用层,应用层就可以直接拿到BBinder了。
发起端:发起端的进程以及实际执行传输的线程,BpBinder。
接收端:与发起端对应的目标进程、线程,BBinder。
传输的数据:即IPCThreadState::writeTrasaction()代码中的binder_transaction_data。可能包含简单的数据,也可能传输的是其它Binder对象,或者是Binder代理对象,或者是Binder实体对象。
参考文章:
http://wangkuiwu.github.io/2014/09/02/Binder-Datastruct/
http://blog.csdn.net/getnextwindow/article/details/47293751
http://blog.csdn.net/getnextwindow/article/details/47294327
http://qiangbo.space/2017-01-15/AndroidAnatomy_Binder_Driver/