安卓进程间通信浅谈

news2025/4/8 19:34:55

Case: /Users/lucas/AndroidStudioProjects/aidldemo-master

一:操作系统

从操作系统原理去看,进程通信主要有三个方法:共享存储、消息传递、管道通信。

二:安卓中的IPC

进程间通信的几种方式:Intent(Bundle),文件共享,Messenger,AIDL,ContentProvider,Socket等。

  • Bundle实现了Parcelable接口
    • 优点:简单易用
    • 缺点:只能传递Bundle支持的数据类型
    • 使用场景:四大组件间的进程通讯
  • 文件共享
    • 优点:简单易用
    • 缺点:不适合高并发的场景,不能做到即使通讯
    • 使用场景:无并发访问的情景,简单的交换数据,实时性要求不高
  • AIDL
    • 优点:功能强大,支持一对多并发通讯,支持实时通信
    • 缺点:一定要处理好线程同步的问题
    • 使用场景:一对多进行通讯,有RPC(远程过程调用协议)的需求
  • Message
    • 优点:功能一般,支持一对多串行通讯,支持实时通信
    • 缺点:不能更好的处理高并发场景,不支持RPC,数据通过Message进行传输,因此只能支持Bundle支持的数据类型
    • 使用场景:低并发的一对多的实时通讯,没有RPC的需求或者说没有返回结果的RPC
  • ContentProvider
    • 优点:主要用于数据访问,支持一对多的并发数据共享
    • 缺点:受约束,主要支队数据源的曾删改查
    • 使用场景:一对多的数据共享
  • Socket(套接字)
    • 优点:功能强大,通过读写网络传输字节流,支持一对多的并打的实时通讯
    • 缺点:不支持直接的RPC
    • 使用场景:万络数据的交换
  • BroadcastReceiver
    • 优点:操作简单,支持一对多实时通信
    • 缺点:只支持数据单向传递,效率低且安全性不高
    • 使用场景:一对多的低频单向通信

Android之所以选择Binder,有2个方面原因

  • 安全,每个进程都会被Android系统分配UID和PID,不想传统的在数据里加入UID,这就让那些恶意进程无法直接和其他进程通信,进程间通信的安全性得到提升
  • 高效,像Socket之类的IPC每次数据拷贝都需要2次,而Binder只需要一次,在手机上这种资源紧张的情况下很重要

2.1 AIDL

AIDLAndroid中实现跨进程通信(Inter-Process Communication)的一种方式。AIDL的传输数据机制基于BinderBinder对传输数据大小有限制, 传输超过1M的文件就会报android.os.TransactionTooLargeException异常(注1),一种解决办法就是使用匿名共享内存进行大文件传输

2.1:共享内存简介

共享内存是进程间通信的一种方式,通过映射一块公共内存到各自的进程空间来达到共享内存的目的。

shmem.png

对于进程间需要传递大量数据的场景下,这种通信方式是十分高效的,但是共享内存并未提供同步机制,一个进程写共享内存时,并无自动机制可以阻止第二个进程开始对它进行读取,所以我们需要类似信号量机制来同步对共享内存的访问。

Android中的匿名共享内存(Ashmem)是基于Linux共享内存的,借助Binder+文件描述符(FileDescriptor)实现了共享内存的传递。它可以让多个进程操作同一块内存区域,并且除了物理内存限制,没有其他大小限制。相对于Linux的共享内存,Ashmem对内存的管理更加精细化,并且添加了互斥锁。Java层在使用时需要用到MemoryFile,它封装了native代码。Android平台上共享内存通常的做法如下:

  • 进程A通过MemoryFile创建共享内存,得到fd(FileDescriptor)
  • 进程A通过fd将数据写入共享内存
  • 进程A将fd封装成实现Parcelable接口的ParcelFileDescriptor对象,通过BinderParcelFileDescriptor对象发送给进程B
  • 进程B获从ParcelFileDescriptor对象中获取fd,从fd中读取数据

2.2:AIDL使用方法

服务端:1.创建接口,2.定义binder,实现接口,3.创建服务,返回binder;

客户端:1.绑定服务,2.实现ServiceConnection绑定监听,3.在绑定成功的回调中,将IBinder转换成AIDL的接口代理对象。

客户端和服务端绑定成功后,就可以通过AIDL的接口代理对象,就像直接调用本地方法一样,调用服务端的方法了。需要注意的是,AIDL间传递的对象要实现Parcelable接口。

2.3:AIDL的回调

原理:和常用的callback接口是一样的,只不过aidl的callback回调是在两个进程内。

服务器:ITaskBinder.Stub() + callback接口

客户端:定义一个calback的具体实现,拿服务端service ,里面register这个callback,然后服务端ITaskBinder.Stub() ->里面callback.xx(),于是调用到客户端定义的callback实现

在aidl文件中,通过oneway修饰,申明方法为异步

2.4:AIDL的底层:binder

两者关系:

AIDL定义的接口,它除了是一个接口以外,它还是一个Binder对象,支持在接口和Binder之间相互转换(asBinder(), asInterface())。创建了AIDL接口后,系统会自动生成其对应的Binder类,它继承了IInterface, 内部有一个静态抽象类Stub和Stub内部的Proxy类。其中Stub继承了Binder类,所以AIDL中的Stub即为一个Binder对象。

binder:

从代码的角度来说,Binder 是 Android 系统源码中的一个类,它实现了 IBinder 接口;

从 IPC 角度来说,Binder 是 Android 中的一种跨进程通信方式;

从 Android Framework 角度来讲,Binder 是 ServiceManager 连接各种 Manager(ActivityManager、WindowManager 等等)和相应 ManagerService 的桥梁;

从 Android 应用层来说,Binder 是客户端和服务端进行通信的媒介,当 bindService 的时候,服务端会返回一个包含了服务端业务调用的 Binder 对象,通过这个 Binder 对象,客户端就可以和服务端进行通信,这里的服务包括普通服务和基于 AIDL 的服务。

AIDL的作用是实现跨进程通讯使用方法也非常的简单,他的设计模式是典型的C/S架构。客户端通过绑定服务端,获取了服务端的IBinder对象,这个IBinder对象,就是代理模式中的那个代理(或者说是c语音中的指针,指向了服务端),然后客户端通过这个代理对象,就可以通过transact方法,向服务端发送数据,实现了进程间的通讯。

2.1 Intent

使用例子:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.putData...  //放一些你需要传递的数据
ComponentName componentName = new ComponentName("com.lucas.test", "com.lucas.test.Main2Activity");//要跳转的包名以及类名
intent.setComponent(componentName);
startActivity(intent);

弊端:Intent 只能传递简单的对象,对象必须实现Pacelable接口序列化。

三:(补充)Binder数据限制

Binder传输数据限制原因:

  • 1.每个进程中会有多个Binder线程,而这些Binder线程又共享创建进程的时候开辟的1M-8K的内存空间,所以在每个Binder线程传输数据的时候,不可能传递1M-8K;
  • 2.另外开辟的这部分内存空间,还会有一些堆栈以及代码块等占用部分内存。

注意

  • 注1:普通的由 Zygote fork 而来的用户进程,所映射的Binder内存大小是不到1M的,准确说是#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))这个限制定义在 frameworks/native/+/4d2f4bb/libs/binder/ProcessState.cpp类中,如果传输数据超过这个大小,系统就会报错,因为Binder本身就是为了进程间频繁而灵活的通信所设计的,并不是为了拷贝大数据而使用的。

参考

一道面试题:使用AIDL实现跨进程传输一个2M大小的文件:https://juejin.cn/post/6990379493235884062

Android intent 传递数据的大小限制:https://blog.csdn.net/u011033906/article/details/117276922

Android 跨进程通信-(十)Binder机制传输数据限制—罪魁祸首Binder线程池:https://blog.csdn.net/nihaomabmt/article/details/116701810

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

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

相关文章

使用Visual Studio打造强大的程序,从添加第三方库开始

使用Visual Studio打造强大的程序,从添加第三方库开始 博主简介一、引言二、理解第三方库三、下载和安装第三方库四、示例代码和演示五、总结 博主简介 💡一个热爱分享高性能服务器后台开发知识的博主,目标是通过理论与代码实践的结合&#x…

Vscode自定义注释模板

首先安装插件Doxygen Documentation Generator,安装完成之后点击Doxygen插件的设置,按照下面的步骤打开settings.json进行编辑: 在settings.json中追加如下代码: "doxdocgen.file.copyrightTag": ["Copyright (C),…

如何在Arch Linux上安装最新的GNOME Alpha/Beta版本

导读这是为那些想在 Arch Linux 上安装下一个主要版本的 GNOME 桌面环境的 alpha 或 beta 开发版的用户提供的快速而又肮脏的教程,仅供测试之用。 每次有新的 GNOME alpha 版本发布,人们都会问我如何在各种 GNU/Linux 发行版上安装。我总是告诉他们&…

SUM(整除分块)

题目描述 给定 x ,y , 求 的值 . 其中 , 代表向下取整 输入描述 第一行一个正整数 T(1≤T≤100), 表示测试用例的数目。每个测试用例占一行。 接下来的 T 行,每行两个正整数 x, y 。 输出描述 输出共 T 行,…

Laravel文档阅读笔记-How to enable CORS on Laravel

使用中间件为http响应头添加Access-Control-Allow-Origin 1.创建Cors中间件&#xff1a; $ php artisan make:middleware Cors 2.编辑中间件&#xff1a; <?phpnamespace App\Http\Middleware;use Closure;class Cors {/*** Handle an incoming request.** param \Ill…

wordpress后台的路径都是空白,进不了后台怎么办?

主题或插件冲突&#xff1a;某些主题或插件可能与其他已安装的主题或插件不兼容&#xff0c;导致登录页面显示为空白。您可以通过禁用所有插件和将主题更改为默认主题来查看是否解决了问题。如果解决了问题&#xff0c;则可以逐个重新启用插件以找出是哪个插件造成冲突。 PHP错…

Express 框架介绍

目录 1、简介 1.1 Web 应用 1.2 API 1.3 性能 1.4 框架 2、如何开始 Express 编程之旅 3、测试实例 4、其他问题 4.1 如何定义模型&#xff1f; 4.2 Express 支持哪些模板引擎&#xff1f; 4.3 如何处理 404 响应&#xff1f; 4.4 如何设置错误处理程序&#xff1f…

Python3模拟π的求值过程

假设我们已经知道了圆的面积计算公式是&#xff1a;πr&#xff0c;正方形的面积是r&#xff0c;但是不知道π的具体值。模拟结果如图所示&#xff1a;我们将1/4圆的面积s1比上正方形的面积s2就能得出1/4π&#xff0c;所以π就等于4倍的s1/s2。 图中横纵坐标轴最大值均为1&am…

无人驾驶中如何识别颜色并跟踪的具体应用

摄像头对于颜色的识别&#xff0c;我们在上一篇文章中有具体的介绍&#xff0c;并介绍了OpenCV中的一些常见知识点&#xff0c;这里我们来对颜色识别在无人驾驶中&#xff0c;做一个具体应用。 有兴趣的可以先看下本人拍摄的一个视频&#xff1a;无人车识别颜色并跟踪 通过…

PICO4开发实战一:节奏光剑(VR)(需求文档)

PICO4开发实战一&#xff1a;节奏光剑&#xff08;VR&#xff09;&#xff08;需求文档&#xff09; 文章目录 PICO4开发实战一&#xff1a;节奏光剑&#xff08;VR&#xff09;&#xff08;需求文档&#xff09;一、V1 基础功能开发1、V1版本完成页面2、V1基本功能需求介绍&am…

81. 正则表达式

一、概述二、匹配单个字符三、匹配一组字符四、使用元字符五、重复匹配六、位置匹配七、使用子表达式八、回溯引用九、前后查找十、嵌入条件参考资料 一、概述 正则表达式用于文本内容的查找和替换。 正则表达式内置于其它语言或者软件产品中&#xff0c;它本身不是一种语言或…

学习react,复制一个civitai(C站)-更新3

更新内容 优化了一下加载速度 图片列表 初步更新了199张图片&#xff0c;大部分都有stable diffusion 的prompts。 可以直接复制到AI绘画里面使用。 先来看看效果图吧&#xff1a; 我还是挺喜欢这种砌砖流布局 技术点 同样使用了砌墙瀑布流布局:masonry js 安装方法 npm …

配置Propos检验

配置Propos检验 ​ 和vue不同react并未为我们直接配置props校验&#xff0c;(类型必填默认值),需要我们就手动进行配置

SqlServer数据库【基础-更删改查】

一、创建语句 &#xff08;1&#xff09;创建数据库 1.检查系统中是否存在这个数据库&#xff0c;存在则删除 格式&#xff1a; if exists(select * from sysdatabases where name数据库名) drop database 数据库名 go例子&#xff1a; if exists(select * from sysdataba…

Redis事务(4)

⭐ 作者简介&#xff1a;码上言 ⭐ 代表教程&#xff1a;Spring Boot vue-element 开发个人博客项目实战教程 ⭐专栏内容&#xff1a;个人博客系统 ⭐我的文档网站&#xff1a;http://xyhwh-nav.cn/ 文章目录 Redis事务1、Redis事务概念2、应用1、MULTI开启事务2、事务失败…

【数据库】数据库索引结构分析,MySQL单表最多能存放多少数据

经常听到MySQL单表最多能存放2千万数据&#xff0c;多了就要考虑分表&#xff0c;依据是什么呢&#xff1f; 本文以MySQL为例&#xff0c;默认数据页大小是16KB。 索引内容结构 非叶子节点 主键页号 假如&#xff1a; 主键是bigint&#xff0c;8bit&#xff1b;页号是4bit&…

Vue中v-html用法以及指令汇总

操作数组的方法 &#xff1a; push&#xff1a;数组最后位置新增元素 pop&#xff1a; 删除最后一个元素 shift&#xff1a; 删除第一个元素 unshift&#xff1a;往前面加一个元素 splice&#xff1a;在数组的指定位置插入、删除、替换一个元素 sort&#xff1a; 数组排序…

力扣算法数学类—Excel表列名称

目录 Excel表列名称 题解&#xff1a; 代码&#xff1a; Excel表列名称 168. Excel表列名称 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数 columnNumber &#xff0c;返回它在 Excel 表中相对应的列名称。 例如&#xff1a; A -> 1 B -> 2 C -> 3 ... Z -…

CENTOS安装 graylog5.0

我们直接开始 基础环境和java sudo yum install epel-release 并安装带有 sudo yum install pwgenyum install java-1.8.0-openjdk-headless.x86_64 MONGODB 安装数据库 6.0 [mongodb-org-6.0] nameMongoDB Repository baseurlhttps://repo.mongodb.org/yum/redhat/$relea…

ensp静态路由

要求&#xff1a; 1.全网可达 2.拓朴中所需地址全部基于192.168.0.0/24 3.静态路由&#xff08;不许使用其他动态&#xff09; 4.R2环回需要汇总 拓朴图&#xff1a; 将192.168.0.0/24划分为5个子网&#xff0c; 得&#xff1a; 192.168.0.0/27 192.168.0.32/27 192.168.0.64/…