Android 13(T) - binder阅读(5)- 使用ServiceManager注册服务2

news2024/11/20 1:39:35

上一篇笔记我们看到了binder_transaction,这个方法很长,这一篇我们将把这个方法拆分开来看binder_transaction做了什么,从而学习binder是如何跨进程通信的。

1 binder_transaction

static void binder_transaction(struct binder_proc *proc,
			       struct binder_thread *thread,
			       struct binder_transaction_data *tr, int reply,
			       binder_size_t extra_buffers_size)

首先我们来看函数的参数,第一个参数proc为调用进程的binder_proc(也就是MediaServer进程所有的binder_proc);第二个参数thread我们这里不讨论,主要用于多任务通信;第三个参数tr为从用户空间拷贝过来的binder_transaction_data

函数一开始声明了一串变量,我们挑出一部分给出注释:

	// 目标进程的binder_proc 
	struct binder_proc *target_proc = NULL;
	// 目标进程的binder_node 
	struct binder_node *target_node = NULL;
	// 上下文(servicemanager)
	struct binder_context *context = proc->context;
	// 用户空间数据指针
	const void __user *user_buffer = (const void __user *)
				(uintptr_t)tr->data.ptr.buffer;

由于我们这边传递的cmd为BC_TRANSACTION,所以这里先不看reply分支的内容:

		// 1. 判断target handle是否为0,如果不为0则进入以下分支
		if (tr->target.handle) {
			struct binder_ref *ref;
			// 2. 查找binder_ref
			ref = binder_get_ref_olocked(proc, tr->target.handle,
						     true);
			if (ref) {
				target_node = binder_get_node_refs_for_txn(
						ref->node, &target_proc,
						&return_error);
			} 
		} else {
		// 3. 如果target handle为0,如果不为0则target为servicemanager
			// servicemanager的binder_node可以从proc->context中获得
			target_node = context->binder_context_mgr_node;
			if (target_node)
				target_node = binder_get_node_refs_for_txn(
						target_node, &target_proc,
						&return_error);
		}

以上代码是根据Handle查找目标进程的binder_node,这里分了两种情况:

  1. handle为0,说明目标进程为ServiceManager,binder_context 存储的binder_node即为ServiceManager进程所属的。
  2. handle不为0,说明是其他进程,这里要引出一个新的结构体变量binder_ref,这个东西在我们每次从servicemanager获取服务代理时,由binder驱动帮助我们创建,binder_ref用于存储服务的进程信息,除此之外binder驱动为该代理创建一个handle也存储在binder_ref中,有了这个handle就可以找到目标进程了,最后把创建的binder_ref存储在调用进程的binder_proc的一个红黑树列表中。
    这里讲的可能比较拗口,用一张图来表示下:
    请添加图片描述

我们还是回到handle为0的情况,调用servicemanager注册服务的流程中。接下来这部分我没有仔细去研究,没太看懂,只能写一些我的猜测在这里,大概就是从用户空间拷贝我们一开始打包的Parcel数据到目标进程的共享内存当中:

	struct binder_transaction *t;
	t = kzalloc(sizeof(*t), GFP_KERNEL);
	t->to_proc = target_proc;
	t->to_thread = target_thread;
	t->code = tr->code;
	t->flags = tr->flags;
	t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
		tr->offsets_size, extra_buffers_size,
		!reply && (t->flags & TF_ONE_WAY), current->tgid);
	t->buffer->transaction = t;
	t->buffer->target_node = target_node;
	t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
	if (binder_alloc_copy_user_to_buffer(
				&target_proc->alloc,
				t->buffer,
				ALIGN(tr->data_size, sizeof(void *)),
				(const void __user *)
					(uintptr_t)tr->data.ptr.offsets,
				tr->offsets_size)) {
	}

仅仅做完拷贝还没结束,还需要对拷贝的buffer中的一些特殊内容做一些处理,我这里只看是如何处理传递过来的binder对象的:

		hdr = &object.hdr;
		off_min = object_offset + object_size;
		switch (hdr->type) {
		case BINDER_TYPE_BINDER:
		case BINDER_TYPE_WEAK_BINDER: {
			struct flat_binder_object *fp;

			fp = to_flat_binder_object(hdr);
			ret = binder_translate_binder(fp, t, thread);
		} break;
		case BINDER_TYPE_HANDLE:
		case BINDER_TYPE_WEAK_HANDLE: {
			struct flat_binder_object *fp;
			fp = to_flat_binder_object(hdr);
			ret = binder_translate_handle(fp, t, thread);
		} break;

这里主要看binder_translate_binder是如何translate处理的:

static int binder_translate_binder(struct flat_binder_object *fp,
				   struct binder_transaction *t,
				   struct binder_thread *thread)
{
	struct binder_node *node;
	struct binder_proc *proc = thread->proc;
	struct binder_proc *target_proc = t->to_proc;
	struct binder_ref_data rdata;
	int ret = 0;
	// 1 从调用进程中查找要传递的binder对象的binder_node
	node = binder_get_node(proc, fp->binder);
	if (!node) {
		// 2 如果没有查找到,为调用进程创建一个binder_node
		node = binder_new_node(proc, fp);
		if (!node)
			return -ENOMEM;
	}
	// 3 查找目标进程是否已经存储有这个binder_ref,如果没有则为其创建一个binder_ref
	ret = binder_inc_ref_for_node(target_proc, node,
			fp->hdr.type == BINDER_TYPE_BINDER,
			&thread->todo, &rdata);
	if (ret)
		goto done;
	// 将binder实体转换为了引用
	if (fp->hdr.type == BINDER_TYPE_BINDER)
		fp->hdr.type = BINDER_TYPE_HANDLE;
	else
		fp->hdr.type = BINDER_TYPE_WEAK_HANDLE;
	fp->binder = 0;
	fp->handle = rdata.desc;
	fp->cookie = 0;
done:
	binder_put_node(node);
	return ret;
}

这里主要做了如下几件事情:

  1. 从调用进程中查找要传递的binder对象的binder_nodebinder_proc中同样有一个红黑树链表存储有该进程中的binder_node对象;
  2. 如果没有查找到,为调用进程创建一个binder_node,说明传递的对象是属于调用进程的;
  3. 查找目标进程是否已经有了binder_node对应的binder_ref,如果没有则说明目标进程还没有这个要传递的binder对象的引用,为目标进程创建一个binder_ref引用(handle),存储到flat_binder_object 中写到共享内存当中。

binder驱动会将我们传递的binder实体转化为属于调用进程的binder_node,并且提供一个binder_ref给目标进程,目标进程持有的永远都是代理。
请添加图片描述
到这里,binder数据的传输就结束了。


总结:这一篇笔记写的比较水,最重要的共享内存并没有理解清楚,有想了解的小伙伴可以去看看其他大神的博文。其实我的目标是研究binder对象是如何传输的,到这里也大概也了解了,目的也算达成,后续有机会再去研究共享内存机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/699440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何将自定义起步依赖打成包

说明:之前做过一个自定义的OSS起步依赖(http://t.csdn.cn/9aYr5),但是当时只是新建了一个Demo模块来测试自定义起步依赖能成功使用,本文介绍如何把自定义的起步依赖打成jar包,供其他项目或其他人引入依赖就…

华为云CodeArts TestPlan测试设计:守护产品开发质量之魂

华为产品质量的守护神 华为云CodeArts TestPlan测试设计是华为产品质量的守护神。华为云CodeArts TestPlan提供多维度测试设计模板、“需求-场景-测试点-测试用例” 四层测试分解设计能力,启发测试人员发散性思维,对项目环境、测试对象、质量标准、测试…

【SpringBlade-权限缺陷】API鉴权逻辑缺陷漏洞

目录 一、理论部分 简介 如何通过认证 API 鉴权 配置API放行 细颗粒度鉴权配置 结尾 二、实战部分 一、理论部分 简介 Secure 基于 JWT 封装,每次请求的时候,会拦截到需要鉴权的API请求,并对其请求头携带的Token进行认证。若 Token…

Js时间倒计时

😇作者介绍:一个有梦想、有理想、有目标的,且渴望能够学有所成的追梦人。 🎆学习格言:不读书的人,思想就会停止。——狄德罗 ⛪️个人主页:进入博主主页 🗼推荐系列:点击进入 &#…

vue 0-1搭建项目

vue 从0-1搭建项目 前提:进入到需要创建项目的文件夹中,打开命令行窗口 windowsr 打开命令行窗口 创建vue2.0项目: 自动创建 1.vue create 项目名称 仅包含3个功能:vue2/3,babel,eslint 手动创建 1.vue create 项目名…

ModaHub魔搭社区:详解向量数据库Milvus的Mishards:集群分片中间件(五)

目录 在 Kubernetes 中部署 Mishards 集群 安装前提 安装流程 卸载 Mishards 从单机升级到 Mishards 集群 注意事项 基本案例 在 Kubernetes 中部署 Mishards 集群 安装前提 Kubernetes 版本 1.10 及以上Helm 版本 2.12.0 及以上 关于 Helm 的使用请参考 Helm 使用指…

【python入门系列】第一章:Python基础语法和数据类型

文章目录 前言一、简单语法1. 注释 这是一个单行注释2. 变量 二、数据类型1.字符串2.整数3.浮点数4.布尔值5.列表 三、运算符1.算术运算符:用于执行基本的算术操作,如加、减、乘和除。2.比较运算符:用于比较两个值的大小或相等性。3.逻辑运算…

01.网络编程-基础概念

网络编程就是指编写互联网项目,项目可以通过网络传输数据进行通讯 网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的 1.1 软件结构…

Oracle 11g安装配置完美教程 - Windows

写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域,如今终有小成…

用Java解决华为OD机试考题,目标300+真题,清单奉上,祝你上岸

华为OD机考大纲 其它语言版本华为 OD 机试题清单(机试题库还在逐日更新)详细大纲 其它语言版本 本目录为华为od机试JS题解目录,其它版本清单如下 ⭐️华为OD机考 Python https://blog.csdn.net/hihell/category_12199275.html ⭐️华为OD机考…

BOSHIDA DC电源模块低温试验检测详细分析

BOSHIDA DC电源模块低温试验检测详细分析 DC电源模块的低温试验是电源应用领域中的一项重要测试,它可以检测模块在低温环境下的性能表现是否与设计要求相符。这是因为在一些极端环境下,电源模块的性能会受到影响,从而影响整个系统的运行稳定…

山西电力市场日前价格预测【2023-06-30】

日前价格预测 预测明日(2023-06-30)山西电力市场全天平均日前电价为362.38元/MWh。其中,最高日前价格为477.68元/MWh,预计出现在21: 15。最低日前电价为247.28元/MWh,预计出现在13: 00。以上预测仅供学习参考&#xff…

Pytorch深度强化学习(3):详解K摇臂赌博机模型和ϵ-贪心算法

目录 1 K-摇臂赌博机2 ϵ \epsilon ϵ-贪心算法3 softmax算法4 Python实现与分析 1 K-摇臂赌博机 单步强化学习是最简单的强化学习模型,其以贪心策略为核心最大化单步奖赏 如图所示,单步强化学习的理论模型是 K K K-摇臂赌博机( K K K-armed bandit)&…

内部类之成员内部类

我们在阅读源码的过程中,会遇到很多内部类,让我们阅读难度增加。这篇文章主要介绍成员内部类的作用 1.成员内部类可以访问外部类的所有方法和成员变量(不论是静态的还是非静态的) package com.high.concurrency.inner;/*** auth…

如何让chatgpt给我们实现一个桌面便签?

我: 用Java开发一款桌面便签软件。功能需求:1、便签可以钉在桌面任意角落;2、便签内容实时保存到本地;3、有新增按钮,点击新增时清除当前面板上的内容,新建一条新的便签内容,并保存到本地&#…

通往AGI之路:揭秘英伟达A100、A800、H800、V100在高性能计算与大模型训练中的霸主地位

AGI | NLP | A100 | H100 | Nvidia | Aurora GPT| LLM | A800 | V100 | Intel | ChatGPT 日前,随着深度学习、高性能计算、大模型训练等技术的保驾护航,通用人工智能时代即将到来。各个厂商也都在紧锣密鼓的布局,如英伟达前段时间发布GH 200…

C3.ai:一个即将“破灭”的人工智能泡沫

来源:猛兽财经 作者:猛兽财经 C3.ai仅适用于能承受高风险波动的投资者 猛兽财经曾在之前分析过C3.ai(AI)这家公司,认为C3.ai可能在借助人工智能热潮炒作自己。截止撰写本文时,C3.ai的股价已跌到了到2…

使用ganymed-ssh2连接linux报错 Cannot negotiate, proposals do not match

ganymed-ssh2连接linux报错 背景报错信息解决方案:运行成功 背景 最近有个项目,需要在Linux下的服务器内写了一部分Python脚本,业务处理却是在Java内,那么就想能不能在Java里面,来远程执行Linux下的Python脚本&#x…

chatgpt赋能python:使用Python连接网络摄像头

使用Python连接网络摄像头 网络摄像头是现代生活中不可或缺的设备之一,其允许用户在远程位置查看实时视频流。Python语言提供了强大的工具来连接和控制网络摄像头。本文将向您展示如何使用Python连接网络摄像头以及如何将视频流数据流式传输到本地计算机。 环境设…

【AUTOSAR】BMS开发实际项目讲解(十九)----电池管理系统系统设计电池单体过放后再充电保护

电池单体过放后再充电保护 关联的系统需求 TSR-BMS-2101、TSR-BMS-2102、TSR-BMS-2103、TSR-BMS-2104、TSR-BMS-2105、TSR-BMS-2106、TSR-BMS-2107、TSR-BMS-2108、TSR-BMS-2109、TSR-BMS-2110、TSR-BMS-2111、TSR-BMS-2112、TSR-BMS-2113、TSR-BMS-2114、TSR-BMS-2115、TSR-B…