Binder 机制分析 Android 内核源码中的 Binder 驱动源码 binder.c ( googlesource 中的 Android 内核源码 | 内核源码下载 )
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Binder 机制分析 Android 内核源码中的 Binder 驱动源码 binder.c ( googlesource 中的 Android 内核源码 | 内核源码下载 )相关的知识,希望对你有一定的参考价值。
文章目录
一、查看 android 内核源码中的 Binder 驱动源码 binder.c
Android 内核源码地址 : https://android.googlesource.com/kernel/
选择 common 版本的内核 ;
common 版本内核 : https://android.googlesource.com/kernel/common/
选择 android-mainline 分支 ;
跳转到 https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline 页面 ,
选择该页面下的 drivers 驱动目录 ,
进入 https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/drivers/ 页面 ,
选择 android 目录 , 查看 Android 相关驱动 ;
跳转到 https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/drivers/android/ 目录 ,
其中的 binder.c 就是 Binder 驱动源码 ;
binder.c 源码地址 https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/drivers/android/binder.c
二、分析 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;
}
三、博客资源
https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline 内核源码放在了 CSDN 下载中 , 0 积分可下载 ;
下载地址 : https://download.csdn.net/download/han1202012/23353149
以上是关于Binder 机制分析 Android 内核源码中的 Binder 驱动源码 binder.c ( googlesource 中的 Android 内核源码 | 内核源码下载 )的主要内容,如果未能解决你的问题,请参考以下文章