企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
一个进程在使用Binder进程间通信机制之前,首先要调用函数open打开设备文件/dev/binder来获得一个文件描述符,然后才能通过这个文件描述符来和Binder驱动程序交互,继而和其他进程执行Binder进程间通信。 从前面5.1.2小节的内容可以知道,当进程调用函数open打开设备文件/dev/binder时,Binder驱动程序中的函数binder_open就会被调用,它的实现如下所示。 **kernel/goldfish/drivers/staging/android/binder.c** ~~~ static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc; if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE) printk(KERN_INFO "binder_open: %d:%d\n", current->group_leader->pid, current->pid); proc = kzalloc(sizeof(*proc), GFP_KERNEL); if (proc == NULL) return -ENOMEM; get_task_struct(current); proc->tsk = current; INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->wait); proc->default_priority = task_nice(current); mutex_lock(&binder_lock); binder_stats.obj_created[BINDER_STAT_PROC]++; hlist_add_head(&proc->proc_node, &binder_procs); proc->pid = current->group_leader->pid; INIT_LIST_HEAD(&proc->delivered_death); filp->private_data = proc; mutex_unlock(&binder_lock); if (binder_proc_dir_entry_proc) { char strbuf[11]; snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); remove_proc_entry(strbuf, binder_proc_dir_entry_proc); create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc); } return 0; } ~~~ 第8行首先为进程创建一个binder_proc结构体proc,接下来第11行到第20行代码对该binder_proc结构体proc进行初始化。在初始化binder_proc结构体proc的过程中,第12行、第15行和第19行代码分别使用进程的任务控制块current、进程优先级task_nice(current)和进程组ID来初始binder_proc结构体proc的成员变量tsk、default_priority和pid。 第18行将binder_proc结构体proc加入到一个全局hash队列binder_procs中。全局hash队列变量binder_procs的定义如下所示。 **kernel/goldfish/drivers/staging/android/binder.c** ~~~ static HLIST_HEAD(binder_procs); ~~~ Binder驱动程序将所有打开了设备文件/dev/binder的进程都加入到全局hash队列binder_procs中,因此,通过遍历这个hash队列就可以知道系统当前有多少个进程在使用Binder进程间通信机制。 第21行将初始化完成之后的binder_proc结构体proc保存在参数filp的成员变量private_data中。参数filp指向一个打开文件结构体,当进程调用函数open打开设备文件/dev/binder之后,内核就会返回一个文件描述符给进程,而这个文件描述符与参数filp所指向的打开文件结构体是关联在一起的。因此,当进程后面以这个文件描述符为参数调用函数mmap或者ioctl来与Binder驱动程序交互时,内核就会将与该文件描述符相关联的打开文件结构体传递给Binder驱动程序,这时候Binder驱动程序就可以通过它的成员变量private_data来获得前面在函数binder_open中为进程创建的binder_proc结构体proc。 最后,第24行到第29行的if语句块在目标设备上的/proc/binder/proc目录下创建一个以进程ID为名称的只读文件,并且以函数binder_read_proc_proc作为它的文件内容读取函数。通过读取文件/proc/binder/proc/的内容,我们就可以获得进程的Binder线程池、Binder实体对象、Binder引用对象,以及内核缓冲区等信息。