【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;
}

完整代码参考 https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/drivers/android/binder.c


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/drivers/android/binder.c





三、博客资源



https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline 内核源码放在了 CSDN 下载中 , 0 积分可下载 ;

下载地址 : https://download.csdn.net/download/han1202012/23353149

### 微信公众号与服务号的功能和用途区别 #### 功能差异 在功能方面,订阅号和服务号存在显著的不同。对于未经过认证的订阅号而言,无法连接到第三方链接,除非涉及小程序;而未经认证的服务号则可以连接至第三方链接[^1]。 #### 适用场景 当创建者的目的是提供特定的服务时,在不具备认证资格的前提下应优先考虑选择服务号。相反,如果主要意图是以发布文章的形式来进行推广,则订阅号会是一个更为合适的选择[^2]。 #### 发展历程中的变化 自微信公众号于2012年底推出以来,经历了多次更新和发展阶段。最初仅有的基础版本逐渐演变为包含多种类型的平台体系——即后来增加的企业号以及持续改进后的现有形态。这些演变使得当前环境下微信公众账号的选择更加多样化,并且允许运营人员依据实际需求做出最佳决策[^3]。 #### 技术支持层面 值得注意的是,在涉及到技术集成或自动化交互等功能实现上,无论是哪种类型的公众账号都离不开`access_token`这一重要凭证。它作为访问API接口的关键参数之一,在整个应用开发过程中扮演着不可或缺的角色: ```python import requests def get_access_token(appid, secret): url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}" response = requests.get(url).json() return response['access_token'] ``` 此函数用于获取`access_token`,它是发起任何HTTP请求给微信服务器的前提条件[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值