一 Binder是如何做到精确打击的?
我们先问一个问题,Binder 机制到底是如何从代理对象 BpBinder 找到其对应的 Binder 实体呢?难道它有某种制导装置吗?要回答这个问题,我们只能静下心来研究 Binder 驱动的代码。在 Binder系列2 Binder概念及相关接口和类 中,我们曾经介绍过 ProcessState,这个结构是属于应用层次的东西,仅靠它当然无法完成精确打击。其实在 Binder 驱动层,还有个与之相对应的结构,叫做 binder_proc。为了说明问题,我修改了系列2中的示意图,得到下图:
1.1 创建binder_proc
在系列2中我们知道当构造 ProcessState 并打开 Binder 驱动之时,会调用到驱动层的 binder_open() 函数,而 binder_proc 就是在 binder_open() 函数中创建的。新创建的 binder_proc 会作为一个节点,插入一个总链表 binder_procs 中。binder_open() 函数在系列3介绍SMgr 中已经介绍过了,咱们再次回顾下,具体代码可参考 kernel/drivers/staging/android/Binder.c。
驱动层的 binder_open() 的代码如下:
static int binder_open(struct inode *nodp, struct file *filp)
{
struct binder_proc *proc; //对应的进程结构体
struct binder_device *binder_dev;//对应的binder_device
........
proc = kzalloc(sizeof(*proc), GFP_KERNEL);//在驱动层创建binder_proc
........
INIT_LIST_HEAD(&proc->todo); //初始化进程的todo等待队列
........
//获取binder_device,这个binder_device在Binder驱动初始化的时候生成
binder_dev = container_of(filp->private_data, struct binder_device,
miscdev);
//每个进程的context都对应着同一个binder_dev的context
proc->context = &binder_dev->context;
binder_alloc_init(&proc->alloc);
binder_stats_created(BINDER_STAT_PROC);
proc->pid = current->group_leader->pid;
INIT_LIST_HEAD(&proc->delivered_death);
INIT_LIST_HEAD(&proc->waiting_threads);
//把代表当前进程的binder_proc赋值给filp的private_data
//这个非常重要,以后Binder驱动就是根据这个域找到对应的是哪个进程的.
filp->private_data = proc;
mutex_lock(&binder_procs_lock);
//把这个binder_proc链入到全局的 binder_procs中
hlist_add_head(&proc->proc_node, &binder_procs);
mutex_unlock(&binder_procs_lock);
........
return 0;
}
注意,新创建的 binder_proc 会被记录在参数 filp 的 private_data 域中,以后每次执行 binder_ioctl(),都会从 filp->private_data 域重新读取 binder_proc 的。
binder_procs 总表的定义如下:
static HLIST_HEAD(binder_procs);
我们可以在List.h中看到 HLIST_HEAD 的定义:
tools/include/linux/list.h
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
于是 binder_procs 的定义相当于:
struct hlist_head binder_procs = {
.first = NULL };
随着后续不断向 binder_procs 表中添加节点,这个表会不断加长,示意图如下:
1.2 binder_proc中的4棵红黑树
binder_proc 里含有很多重要内容,不过目前我们只需关心其中的几个域:
struct binder_proc {
struct hlist_node proc_node;//用于链接binder_proc到binder_procs中
struct rb_root threads;//Binder线程树,一系列binder_thread的集合
struct rb_root nodes;//Binder节点树,一系列binder_node的集合
struct rb_root refs_by_desc;//引用树,用句柄做索引,一系列binder_ref的集合
struct rb_root refs_by_node;//引用树,用binder_node做索引,一系列binder_ref的集合
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
struct list_head todo;
struct binder_stats stats;