当前位置: 首页 > news >正文

Android中的Binder

binder是Android平台的一种跨进程通信(IPC)机制,从应用层角度来说,binder是客户端和服务端进行通信的媒介。

ipc原理

ipc通信指的是两个进程之间交换数据,如图中的client进程和server进程。

Android为每个进程提供了虚拟内存空间,而每个Android进程只能运行在自己进程所拥有的虚拟内存空间。

内存空间又分为用户空间和内核空间,前者的数据不能进程间共享,但后者可以。图中的Client进程和Server进程就是利用了进程间可以共享各自内核空间的数据,来完成底层通信的工作。

Android的C/S通信机制

C/S通信指的就是Client和Server两个进程的通信,但实际通信时除了包含这两个进程,还有一个Service Manager,它用于管理各种服务。

这些服务通常是Android系统的核心功能模块,例如传感器管理、电源管理、WIFI管理、闹钟服务等等,与Android四大组件中的服务不同。

当一个Server(服务端)想要提供一种服务,首先需要在Service Manager注册该服务;

而当Client(客户端)想要使用Server中的服务时,不能直接访问,而是要从Service Manager获取该服务,才能使用Server所提供的服务,来与Server进行通信。

Binder通信模型

在引入binder机制后,客户端、服务端和Service Manager之间不能通过api直接互相访问,而是与内核空间的binder驱动通过ioctl方式来完成进程间的数据交换。

关键概念

  • Binder实体对象:Binder服务的提供者,类型是BBinder,位于服务端
  • Binder引用对象:Binder实体对象在客户端进程的代表,类型是BpBinder,位于客户端
  • IBinder对象:Binder实体对象和引用对象的统称,也是他们的父类
  • Binder代理对象:又称接口对象,为客户端的上层应用提供接口服务,类型是IInterface

Binder引用对象和代理对象都是服务端进程中的,把它们分离的好处是一个代理对象可以有多个引用对象,方便上层应用使用。

通信过程

注册服务

  1. server进程向binder驱动申请创建服务的binder实体 
  2. binder驱动为这个服务创建位于内核的binder实体和binder引用
  3. 创建完成后,服务端通过binder驱动将binder引用发送给service manager
  4. service manager收到数据后,取出被创建服务的名字和引用,填入一张查找表

通过以上步骤,server进程通过binder驱动完成了在service manager的服务注册。

在注册服务的过程中,server进程是客户端,而service manager是服务端。

获取服务

  1. Client进程利用handle值为0的引用找到service manager
  2. Client进程向service manager发送xxxservice的访问申请
  3. service manager从请求表中获取xxxservice的名字,在查找表中找到对应的条目,取出对应的binder引用
  4. service manager把xxxservice的binder引用传给Client进程

使用服务

在使用服务时,Client和Server进程都是发送方和接收方。 

这是因为Client在发送服务请求时,Server是接收方;当Server返回数据给Client时,Client变成了接收方。

不论发送方是谁,都会通过自身的Binder实体,把数据发送给接收方的Binder引用。binder驱动回处理发送请求,利用内核空间进程共享机制如下:

  1. 把发送方的数据存入写缓存(binder_write_read.write_buffer)(对于接收方这是读缓存)
  2. 接收方一直处于阻塞状态,当写缓存有数据,会读取数据执行命令操作
  3. 接收方执行操作后,会把结果返回,同样放在写缓存区(对于发送方这是读缓存)

Android中的Binder

 activity、service等组件都需要与ams(system_server)通信,这种跨进程的通信是由binder完成的。从不同角度分析binder如下:

  • 机制:binder是一种进程间通信机制
  • 驱动:binder是一个虚拟物理设备驱动
  • 应用层:binder是一个能发起通信的java类:在java中,如果想要进程通信,就要继承binder

为什么要使用多进程进行开发?

虚拟机分配给各个进程的运行内存是有限制的,lmk也会优先回收占用系统资源大的进程。

对于多进程开发的优势一般有以下几点:

  • 突破进程内存限制,为占用内存大的单独开辟一个进程
  • 功能稳定性:如为通信线程保持长连接的稳定性
  • 防止内存泄漏:如为容易内存泄漏的webview单独开辟一个进程
  • 隔离风险:对于不稳定的进程放在独立进程,避免主进程崩溃

Binder有什么优势 

首先回顾linux进程间的通信机制:管道、信号量、共享内存、socket。

从性能出发,共享内存 > binder > 其他ipc。

但共享内存的缺点也十分明显。与线程之间共享同一块内存相同,共享内存的进程也很容易出现死锁、数据不同步等问题,操作不方便。同时,socket作为一款通用接口,开销过大。

最重要的一点是安全性。传统ipc模式普遍存在的问题是依赖上层协议和访问接入点是开放的。

以创建服务为例,系统需要知道创建人的身份,但在传统ipc机制中,这个身份的获取是从上层协议获取的,即app将id传给系统,而app传回的内容可以是不真实的。对比之下,服务在被创建时,binder就会为创建人分配唯一的uid(用户身份)。

第二点以服务器为例,如果ip是开放的,服务器很容易就会被攻击。同样的,对于传统ipc,如果接入点被知晓,所有人都可以访问。对比之下,binder同时支持实名和匿名。实名与传统ipc相同,是开放的;匿名指的是如果有人需要获取服务,需要先获取到binder内部的引用,才能进行访问。通常的,系统服务是实名的,个人服务是匿名的。直接在service manager中注册的服务是实名的。

Binder是如何做到一次拷贝的

在回答问题之前详细解释一下ipc和虚拟内存的概念。

进程间通信和线程间不同的原因是两者的内存机制不同。对于线程而言,它们的内存是共享的,但进程之间的内存是相互隔离的。

在ipc原理中我们看到进程内部分为用户空间和内核空间,出于安全两者之间是隔离的,app和系统分别处理用户空间和内核空间。

设想如果进程中没有对这两部份进行隔离,app就可以任意访问系统才能访问的数据,而正常来说这样的访问是需要权限的。但这不意味着两者之间完全隔离。系统为两者通信提供了api(copy_from_user & copy_to_user),使得两者间可以互相通信。

对于我们编程而言,需要系统分配虚拟内存,这是因为物理内存不一定是一整块内存,而这种整块内存恰恰是我们在编程中常常需要的。

虚拟内存是通过MMU内存管理单元来映射到物理内存的。在设计的时候,所有进程的内核空间都被映射到了同一块物理内存。这么做的好处就是实现了内存共享,一个进程可以很方便的去获取物理空间中其他进程的内核空间。

 以上就是传统的ipc通信方式。一个进程把自身用户空间的数据通过copy_from_user拷贝到内核空间,而另一个进程通过copy_to_user第二次拷贝从内核空间获取数据到自己的用户空间,这就拷贝了两次。

在binder机制下通信时,内核空间和数据接收方的用户空间映射了同一块物理内存。

简而言之,获取数据的进程的用户空间和内核空间都分配了一小块内存空间,指向同一块物理内存。而这就意味着当被获取数据的进程,从用户空间复制数据到内核空间后,如果内核空间把这个数据存储到这一小块内存空间,另一个进程就能够直接获取,不需要再做一次复制。

MMAP的原理

Linux将一个虚拟内存区域,与磁盘上的物理内存区域关联起来,以这种方式初始化这个虚拟内存区域的内容。这个过程称为内存映射(memory mapping)。

用户空间是不能直接访问磁盘上的内容的,如需访问要通过内核空间,这是肯定很慢的。 首先需要调用write方法从用户空间复制到内核空间,再把数据复制到磁盘,完成写入。

因此当我们使用mmap时关联了虚拟内存和物理内存,当我们在虚拟内存做操作时,物理内存就会直接被修改。

 

相关文章:

Android中的Binder

binder是Android平台的一种跨进程通信(IPC)机制,从应用层角度来说,binder是客户端和服务端进行通信的媒介。 ipc原理 ipc通信指的是两个进程之间交换数据,如图中的client进程和server进程。 Android为每个进程提供了…...

记录一次.gitignore 失效问题

前言 今天使用git同步同事的代码时,出现一个问题,.gitignore限制失效,导致我本地生成的临时缓存文件被跟踪到了commit中,执行 git rm --cache .后再add commit也不行,很奇怪就研究了一下,下面将我的解决方…...

Eclipse 工作空间

Eclipse 工作空间 Eclipse 工作空间(Workspace)是 Eclipse IDE 中一个核心概念,它指的是一个用于组织和存储开发项目及相关文件的目录。在 Eclipse 中,所有开发活动都是围绕工作空间展开的。本文将详细介绍 Eclipse 工作空间的概…...

[240812] X-CMD 发布 v0.4.5:更新 gtb、cd、chat、hashdir 模块功能

目录 📃Changelog✨ gtb✨ cd✨ chat✨ hashdir 📃Changelog ✨ gtb 调整了 fzf 预览窗口中书籍文本的显示效果,通过识别文本中的特殊字符、日期、章节标题等信息,为其赋予不同的颜色。 ✨ cd cd 模块新增功能:在找…...

Flutter中的异步编程

目录 前言 1. Future 和 async/await 1.Future 1.什么是Future? 2.Flutter的三种状态 1.未完成(Uncompleted) 1.定义 2.处理未完成的Future 2.已完成(Completed with a value) 1.概念 2.处理已完成的Future 3.使用async/await 4.Fu…...

vue3 路由带传参跳转;刷新后消失。一次性参数使用。

解决vue3 怎么做到路由跳转传参刷新后消失 解决路由跳转传参去除问题 想要跳转后根据参数显示对应的tab,但url传参刷新会持续保留无法重置。 router.replace替换又会导致显示内容为router.replace后的,传参目的丢失。 业务逻辑: 完成对应操作…...

Unity新输入系统结构概览

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正 在学习新输入系统之前,我们需要对其构成有个印象 1.输入动作(Inputaction) 是定义输…...

18104 练习使用多case解题

### 伪代码 1. 读取第1批测试数据的CASE数量。 2. 处理第1批测试数据,计算每个CASE的最小公倍数并输出。 3. 输出“group 1 done”。 4. 处理第2批测试数据,直到遇到两个0,计算每个CASE的最小公倍数并输出。 5. 输出“group 2 done”。 6. 处…...

【AI人工智能】文心智能体 - 你的专属车牌设计师

引言 自AI盛行以来,不断有各种各样的人工智能产品崭露头角。我们逐步跟着不断产生的人工智能来使自己的工作和生活变得更加智能化!那么我们是否能够创造一款专属于自己的人工智能产品呢? 文心智能体平台就给我们提供了这样的机会&#xff0c…...

Linux-服务器硬件及RAID配置实验

系列文章目录 提示:仅用于个人学习,进行查漏补缺使用。 1.Linux介绍、目录结构、文件基本属性、Shell 2.Linux常用命令 3.Linux文件管理 4.Linux 命令安装(rpm、install) 5.Linux账号管理 6.Linux文件/目录权限管理 7.Linux磁盘管理/文件系统 8.Linu…...

白屏检测系统的设计与实现

目录 一、 什么是白屏问题?二、 问题分析与拆解2.1 人工判定一个白屏问题的逻辑2.2 自动化判定一个白屏问题的算法思想 三、 白屏检测算法3.1 图像灰度化3.2 图像二值化3.3 计算(判定为白屏)置信度 四、 白屏检测系统的设计与实现4.1 UI自动化…...

Real-Time Open-Vocabulary Object Detection:使用Ultralytics框架进行YOLO-World目标检测

Real-Time Open-Vocabulary Object Detection:使用Ultralytics框架进行YOLO-World目标检测 前言相关介绍前提条件实验环境安装环境项目地址LinuxWindows 使用Ultralytics框架进行YOLO-World目标检测进行训练进行预测进行验证 扩展目标跟踪设置提示 参考文献 前言 由…...

区块链用什么编程语言实现?

. 主流区块链的开发语言主要有:C、Go、Java、Rust、C#。 C使用率最高,其次是Go,很少有人用python开发区块链。...

【网络编程】UDP通信基础模型实现

udpSer.c #include<myhead.h> #define SER_IP "192.168.119.143" #define SER_PORT 7777 int main(int argc, const char *argv[]) {//1.创建int sfd socket(AF_INET,SOCK_DGRAM,0);if(sfd -1){perror("socket error");return -1;}//2.连接struct…...

Docker Compose 常用命令详解

Docker Compose 常用命令详解 Docker Compose 是 Docker 官方编排工具之一&#xff0c;用于定义和运行多容器 Docker 应用程序。通过 docker-compose.yml 文件&#xff0c;开发者可以轻松管理服务、网络、卷以及各服务之间的依赖关系。以下将介绍一些常用的 Docker Compose 命…...

超级外链工具,可发9600条优质外链

超级外链工具&#xff0c;是一款在线全自动化发外链的推广工具。使用本工具可免费为网站在线批量增加外链&#xff0c;大大提高外链发布工作效率&#xff0c;是广大草根站长们必备的站长工具。 外链工具只是网站推广的辅助工具&#xff0c;一般适用于短时间内无法建设大量外链…...

VisionPro二次开发学习笔记13-使用CogToolBlock进行图像交互

该程序演示了如何使用CogToolBlock进行图像交互. 从vpp文件中加载一个ToolBlock。 用户可以通过应用程序窗体上的数字增减控件修改ToolBlock输入端子的值。 用户还可以从coins.idb或采集FIFO中选择图像。 “运行一次”按钮执行以下操作&#xff1a; 获取下一个图像或读取下一…...

比特币价格分析:市场重置完成,下一个目标:70,000 美元

比特币再次处于关键支撑位&#xff0c;面临可能影响其短期前景的关键考验。分析师们正密切关注比特币是否重复熟悉的模式&#xff0c;暗示可能出现重大走势。 OKNews分析师Josh表示&#xff0c;比特币一直处于看跌趋势&#xff0c;正如 4 日图上的超级趋势指标所示。这种趋势的…...

大模型笔记5 Extractive QA任务评估

目录 Extractive QA任务评估 Extractive QA评测指标 precision, recall, f1 ROUGE 划分训练与评估数据集 token位置评估 单个token位置评估 输入label的token位置 预测token位置 评估 Wandb 共享机器同时登录 样本类别平衡 标记token label时对窗口进行筛选 训练…...

RCE绕过方式

目录 小于8个字符突破限制 无字母数字执行 php7的做法 php5的思考 PHP5shell 深入理解glob通配符 构造POC&#xff0c;执行任意命令 无参数读文件和RCE总结 代码解读 构造. 另一种构造方法 小于8个字符突破限制 但也只能执行一些非常短的命令&#xff0c;没有什么意义…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...