二、分析 Binder 驱动源码 binder.c
1、binder_ioctl
在 Android Native 层中的 service_manager.c 中的 main 函数中 , 调用了 binder_become_context_manager(bs) , 将自己注册成 Binder 进程的上下文 , 其中调用的 ioctl 方法是内核中的方法 , 这是 IO Control 的简称 ;
int binder_become_context_manager(struct binder_state *bs) { return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); }
上面调用的 ioctl 方法 , 就是下面的内核中的 Binder 驱动源码 binder.c 中的 static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 方法 ;
Native 层传入的 cmd 参数是 BINDER_SET_CONTEXT_MGR , 因此这里的 switch 分支走 case BINDER_SET_CONTEXT_MGR: 分支 , 执行 binder_ioctl_set_ctx_mgr(filp, NULL) 方法 ;
case BINDER_SET_CONTEXT_MGR: ret = binder_ioctl_set_ctx_mgr(filp, NULL); if (ret) goto err; break;
binder.c 相关代码如下 :
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; struct binder_proc *proc = filp->private_data; struct binder_thread *thread; unsigned int size = _IOC_SIZE(cmd); void __user *ubuf = (void __user *)arg; /*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/ binder_selftest_alloc(&proc->alloc); trace_binder_ioctl(cmd, arg); ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret) goto err_unlocked; thread = binder_get_thread(proc); if (thread == NULL) { ret = -ENOMEM; goto err; } switch (cmd) { case BINDER_SET_CONTEXT_MGR: ret = binder_ioctl_set_ctx_mgr(filp, NULL); if (ret) goto err; break; default: ret = -EINVAL; goto err; } ret = 0; err: if (thread) thread->looper_need_return = false; wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret && ret != -EINTR) pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); err_unlocked: trace_binder_ioctl_done(ret); return ret; }
2、binder_ioctl_set_ctx_mgr
在 binder_ioctl 方法中调用了 binder_ioctl_set_ctx_mgr 方法 ,
static int binder_ioctl_set_ctx_mgr(struct file *filp, struct flat_binder_object *fbo) { int ret = 0; // 获取 binder_proc 结构体, 该结构体用于存放 IPC 跨进程请求相关信息 // mmap 一次拷贝机制也与该结构体相关 struct binder_proc *proc = filp->private_data; struct binder_context *context = proc->context; // 该 binder_node 相当于 Binder 的实体 struct binder_node *new_node; kuid_t curr_euid = current_euid(); mutex_lock(&context->context_mgr_node_lock); if (context->binder_context_mgr_node) { pr_err("BINDER_SET_CONTEXT_MGR already set\n"); ret = -EBUSY; goto out; } ret = security_binder_set_context_mgr(proc->tsk); if (ret < 0) goto out; if (uid_valid(context->binder_context_mgr_uid)) { if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) { pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", from_kuid(&init_user_ns, curr_euid), from_kuid(&init_user_ns, context->binder_context_mgr_uid)); ret = -EPERM; goto out; } } else { context->binder_context_mgr_uid = curr_euid; } // 创建 Binder 实体 new_node = binder_new_node(proc, fbo); if (!new_node) { ret = -ENOMEM; goto out; } // 设置 Binder 实体 , 强引用和弱引用次数 + 1 binder_node_lock(new_node); new_node->local_weak_refs++; new_node->local_strong_refs++; new_node->has_strong_ref = 1; new_node->has_weak_ref = 1; context->binder_context_mgr_node = new_node; binder_node_unlock(new_node); binder_put_node(new_node); out: mutex_unlock(&context->context_mgr_node_lock); return ret; }