Android MemoryFile 共享内存
应用场景:
跨进程传输大数据,如文件、图片等;
技术选型:
共享内存–MemoryFile;
优点:
1. 共享内存没有传输大小限制,所以和应用总的分配内存一样(512MB);
2. MemoryFile 是对 SharedMemory 的包装,使用简单便于管理;
实现步骤:
(以A进程共享文件a.txt给B进程为例)
A进程: 创建共享内存空间工具类
public class ShareMemoryUtils {private static ParcelFileDescriptor getPfdFromMemoryFile(final String name, final byte[] bytes) {ParcelFileDescriptor pfd = null;try {long startTime = System.currentTimeMillis();MemoryFile memoryFile = null;try {memoryFile = new MemoryFile(name, bytes.length);memoryFile.allowPurging(true);memoryFile.writeBytes(bytes, 0, 0, bytes.length);pfd = getParcelFileDescriptor(memoryFile);} catch (Exception e) {e.printStackTrace();} finally {closeMemoryFile(memoryFile, null);}}});}return pfd;}private static ParcelFileDescriptor getParcelFileDescriptor(MemoryFile memoryFile) {try {Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor");method.setAccessible(true);FileDescriptor fd = (FileDescriptor) method.invoke(memoryFile);return ParcelFileDescriptor.dup(fd);} catch (Exception e) {e.printStackTrace();return null;}}private static void closeMemoryFile(MemoryFile memoryFile, ParcelFileDescriptor pfd) {if (pfd != null) {try {pfd.close();} catch (IOException e) {e.printStackTrace();}}if (memoryFile != null) {memoryFile.close();}}}
A进程:创建aidl接口,使用binder接口传递文件描述符
interface IMemoryFileApi {ParcelFileDescriptor getParcelFileDescriptor(String type, String params);boolean setParcelFileDescriptor(String type, in ParcelFileDescriptor pfd, String params);oneway void releaseParcelFileDescriptor(String type);
}
B进程:通过bindService连接到A进程,并调用aidl接口获取文件描述符
/*** 通过 binder 接口获取远程进程共享内存的文件描述符*/private ParcelFileDescriptor getParcelFileDescriptor() {try {if (iMemoryFileApi != null) {ParcelFileDescriptor pfd = iMemoryFileApi.getParcelFileDescriptor();return pfd;}} catch (Exception e) {e.printStackTrace();}return null;}
B进程:通过文件描述符读取数据流即可;
注意:
文件描述符在每个进程都有副本,A进程的文件描述符被B进程接收后,实际上已经有了两份文件描述符,即两个进程有各自的内存映射空间。所以B进程读取数据流之后,除了要关闭自己进程的文件描述符对象之外,还要调用接口关闭A进程中的文件描述符;
B进程想要把修改后的文件数据回写给A进程时,需要做的操作和A进程的操作是完全一样的,把文件数据重新创建共享内存,再把文件描述符通过binder接口传递给A进程即可;
总结
网上很多时间比较久的贴子,通过各种反射在A进程获取MemoryFIle来读取共享数据,这种方式并不可取;MemoryFile新版本的封装方式就体现了它的使用方式,Google是希望随时使用随时创建MemoryFile并把文件描述附共享出去这种方式来实现功能的。
android MemoryFile内存共享
进程之间传递数据,由于Binder传递数据有限制1M,所以如果遇到大的数据传递的时候就需要使用使用到MemoryFile内存共享来解决,最合适不过了
首先,MemoryFile是基于Binder自带的transact方法进行传输数据的,因此直接继承Binder即可,不过一般项目中免不了传递一些基本数据类型或者bean数据,因此一般结合aidl一起使用。
android aidl使用记录
- 服务端处理数据
private byte[] buffer = new byte[1024];//public class MyBinder extends IRtcService.Stub {public class MyBinder extends Binder {//此方法Binder自带@Overridepublic boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {LogUtil.e("接收到远端调用" + "code" + code);if (code == 100) {try {ParcelFileDescriptor pfd = data.readParcelable(null);// 或者
// ParcelFileDescriptor pfd = data.readFileDescriptor();FileDescriptor fileDescriptor = pfd.getFileDescriptor();FileInputStream fi = new FileInputStream(fileDescriptor);fi.read(buffer);fi.close();LogUtil.e("--->" + new String(buffer).replace("\0", ""));//返回给客户端reply.writeString("服务器接受数据成功");reply.writeInt(200);return true;} catch (IOException e) {e.printStackTrace();}}return super.onTransact(code, data, reply, flags);}}
- 客户端
private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {try {/****/// 参数1文件名,可为null,参数2文件长度mMemoryFile = new MemoryFile(null, 1024);//在设置了allowPurging为false之后,这个MemoryFile对应的Ashmem就会被标记成"pin",// 那么即使在android系统内存不足的时候,也不会对这段内存进行回收mMemoryFile.allowPurging(false);android.os.Parcel data = android.os.Parcel.obtain();android.os.Parcel reply = android.os.Parcel.obtain();byte[] buffer = "31283216382163812362183621832163812".getBytes();mMemoryFile.writeBytes(buffer, 0, 0, buffer.length);Method getFileDescriptorMethod = mMemoryFile.getClass().getDeclaredMethod("getFileDescriptor");if (getFileDescriptorMethod != null) {FileDescriptor fileDescriptor = (FileDescriptor) getFileDescriptorMethod.invoke(mMemoryFile);// 序列化,才可传送ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fileDescriptor);//写入数据,对应服务端用data.readParcelable(null)接收数据data.writeParcelable(pfd, 0);// 或者,对应服务端用data.readFileDescriptor()接收数据
// data.writeFileDescriptor(fileDescriptor);/*** code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法;* data客户端传递过来的参数;* replay服务器返回回去的值;* flags标明是否有返回值,0为有(双向),1为没有(单向)。*/service.transact(100, data, reply, 0);//服务器返回的值String message = reply.readString();LogUtil.e("--message--->" + message);int code = reply.readInt();LogUtil.e("--code--->" + code);if (code==200){data.recycle();reply.recycle();mMemoryFile.close();mMemoryFile=null;}}} catch (RemoteException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {if (mConnection != null) {try {iRtcService = null;unbindService(mConnection);} catch (Exception e) {}}}};
-
结果
客户端
03-15 21:16:36.011 4327-4327/com.fuyao.elf_android_remote E/elf_remote: --message--->服务器接受数据成功
03-15 21:16:36.011 4327-4327/com.fuyao.elf_android_remote E/elf_remote: --code--->200
服务端
03-15 21:16:36.010 4300-4313/com.fuyao.elf_android_center:rtc_remote E/elf_center: 接收到远端调用code100
03-15 21:16:36.010 4300-4313/com.fuyao.elf_android_center:rtc_remote E/elf_center: --->31283216382163812362183621832163812
Android内存映射文件实现
1. 什么是内存映射文件
内存映射文件是一种将磁盘上的文件映射到内存中的方法。通过内存映射文件,可以将文件的内容直接映射到内存中的一个地址空间,从而可以直接对内存进行读写操作,而无需通过传统的文件IO操作。
在Android开发中,内存映射文件常常用于处理大文件或者需要频繁读写的文件,因为通过内存映射文件可以获得更高的IO性能。
2. Android内存映射文件的实现方式
Android提供了MemoryFile类来实现内存映射文件的功能。MemoryFile是一个基于共享内存的IPC(进程间通信)机制,它允许一个进程将一个内存映射文件映射到另一个进程的地址空间中。
下面是一个简单的代码示例,演示了如何使用MemoryFile实现内存映射文件:
// 创建一个内存映射文件
MemoryFile memoryFile = new MemoryFile("test", 1024);// 向内存映射文件写入数据
String data = "Hello, MemoryFile!";
byte[] buffer = data.getBytes();
memoryFile.writeBytes(buffer, 0, 0, buffer.length);// 从内存映射文件读取数据
byte[] readBuffer = new byte[buffer.length];
memoryFile.readBytes(readBuffer, 0, 0, readBuffer.length);
String readData = new String(readBuffer);// 打印读取的数据
System.out.println(readData);// 释放内存映射文件
memoryFile.close();
在上面的代码中,首先我们创建了一个大小为1024字节的内存映射文件。然后,我们向内存映射文件写入了字符串数据,接着又从内存映射文件中读取了数据,并将其转换为字符串。最后,我们释放了内存映射文件。
需要注意的是,MemoryFile类只能在同一个进程的不同线程之间进行通信,如果需要在不同进程之间通信,则需要使用其他的IPC机制,比如Binder。
3. 内存映射文件的优势和应用场景
内存映射文件相比于传统的文件IO操作有如下优势:
- 更高的IO性能:由于内存映射文件将文件内容映射到内存中,所以可以避免频繁的磁盘IO操作,从而获得更高的IO性能。
- 更低的内存占用:内存映射文件只将文件的部分或全部内容映射到内存中,而不是将整个文件加载到内存中,所以可以减少内存的占用。
- 更方便的数据访问:通过内存映射文件,可以直接对内存中的数据进行读写操作,而无需通过文件IO相关的API,从而简化了数据访问的操作。
内存映射文件常常应用于以下场景:
- 大文件处理:当需要处理大文件时,通过内存映射文件可以获得更高的IO性能。
- 频繁读写文件:当需要频繁读写文件时,通过内存映射文件可以避免频繁的磁盘IO操作,提高程序的响应速度。
- 进程间通信:通过内存映射文件可以在同一个进程的不同线程之间进行通信。
4. 总结
本文介绍了Android内存映射文件的实现方式以及其优势和应用场景。通过内存映射文件,我们可以获得更高的IO性能和更方便的数据访问方式。在处理大文件或者需要频繁读写文件的场景下,使用内存映射文件可以提高程序的性能和响应速度。
相关文章:
Android MemoryFile 共享内存
应用场景: 跨进程传输大数据,如文件、图片等; 技术选型: 共享内存–MemoryFile; 优点: 1. 共享内存没有传输大小限制,所以和应用总的分配内存一样(512MB)࿱…...
【lua】记录函数名和参数(为了延后执行)
需求背景 一个服务缓存玩家信息到对象里,通过对象的函数定时同步到数据库中,如果玩家掉线 清空对象,但是后续步骤导致对象数据需要变更,对象不存在, 就不方便变更了,怎么处理? 方案思考 1.临…...

2023.11.22 数据仓库2-维度建模
目录 1.数仓建设方案 2.数仓结构图,项目架构图 2.1项目架构图 2.2数仓结构图 3.建模设计 4.维度建模 什么是事实表: 什么是维度表: 数据发展模式y以及对应的模型 5.数仓建设规范 数据库划分规范 表命名规范 表字段类型规范 1.数仓建设方案 ODS: 源数据层(临时存储层) 贴…...

pycharm 创建的django目录和命令行创建的django再使用pycharm打开的目录对比截图 及相关
pytcharm创建django的项目 命令行创建的django 命令行创建项目时 不带路径时 (.venv) D:\gbCode>django-admin startproject gbCode 命令行创建项目时 带路径时 -- 所以如果有目录就指定路径好 (.venv) D:\gbCode>django-admin startproject gbCode d:\gbCode\...

【Pytorch】Visualization of Fature Maps(2)
学习参考来自 使用CNN在MNIST上实现简单的攻击样本https://github.com/wmn7/ML_Practice/blob/master/2019_06_03/CNN_MNIST%E5%8F%AF%E8%A7%86%E5%8C%96.ipynb 文章目录 在 MNIST 上实现简单的攻击样本1 训练一个数字分类网络2 控制输出的概率, 看输入是什么3 让正确的图片分…...

【目标检测】保姆级别教程从零开始实现基于Yolov8的一次性筷子计数
前言 一,环境配置 一,虚拟环境创建 二,安装资源包 前言 最近事情比较少,无意间刷到群聊里分享的基于百度飞浆平台的一次性筷子检测,感觉很有意思,恰巧自己最近在学习Yolov8,于是看看能不能复…...

笔记:内网渗透流程之信息收集
信息收集 首先,收集目标内网的信息,包括子网结构、域名信息、IP地址范围、开放的端口和服务等。这包括通过主动扫描和渗透测试工具收集信息,以及利用公开的信息源进行信息搜集。 本机信息收集 查看系统配置信息 查看系统详细信息…...

【2023.11.23】JDBC基本连接语法学习➹
1.导入jar包依赖:mysql-connector-java-8.0.27.jar 2.连接数据库! 3.无法解析类->导入java.sql.*,(将项目方言改为Mysql) JDBC,启动!! public class Main {public static voi…...
ubuntu 安装python3.13
列出 /usr/bin/ 目录下所有以 python 开头的文件和目录 ls /usr/bin/python* 添加Python软件源。您可以通过以下命令将Python的软件源添加到您的系统中 sudo add-apt-repository ppa:deadsnakes/ppa 然后运行以下命令以更新软件包列表: sudo apt-get update 安…...
OpenCV数据类型及CV_16UC1深度图ros订阅
最近用到深度图,对其数据类型及显示有些迷惑,记笔记于此: 目录 一、cv::Mat 的数据类型及转换方式1. cv::Mat 数据类型2. cv::Mat 数据类型互转2.1 OpenCV数据类型转换的函数2.2 可视化深度图像(CV_16UC1)二、cv::Mat 与 sensor_msgs::msg::Image 互转(基于cv_bridge)1.…...

华清远见嵌入式学习——网络编程——小项目
项目要求: 代码实现: 服务器端: #include <myhead.h>//定义协议包 struct proto {char type;char name[20];char text[128]; };int main(int argc, const char *argv[]) {//判断从终端输入的字符串的个数if(argc ! 3){printf("…...
分库分表、分布式数据库、MPP
分库分表、分布式数据库、MPP的区别吗? 一、MySQL分库分表和MySQL分布式集群在性能方面各有优劣,具体取决于应用场景和需求。 MySQL分库分表: 在分库分表的场景下,可以将负载分散到多个数据库实例上,从而提高整体性能…...

浅学指针(2)数组函数传值调用
系列文章目录 文章目录 系列文章目录前言1. 指针的使⽤和传址调⽤结论:实参传递给形参的时候,形参会单独创建⼀份临时空间来接收实参,对形参的修改不影响实 参。那么这个时候,就要搬出指针大哥,在main函数中将a和b的地…...

C++之unordered_map/set的使用
前面我们已经学习了STL中底层为红黑树结构的一系列关联式容器——set/multiset 和 map/multimap(C98). unordered系列关联式容器 在C98中, STL提供了底层为红黑树结构的一系列关联式容器, 在查询时效率可达到log2N,即最差情况下需要比较红黑树的高度次, 当树中的节点非常多时,…...

docker打包chatpdf(自写)
docker打包上传 docker build -t kitelff/chatpdf:v0.1 .##修改镜像名字 docker tag c2c1a0eb4e08 kitelff/chatpdf:v0.1## push docker push kitelff/chatpdf:v0.1上传文件,测试效果...

shell基础
一.Shell脚本编程概述 1.基本概念 将要执行的命令按顺序保存到一个文本文件; 给该文件可执行权限; 可结合各种Shell控制语句以完成更复杂的操作。 2.作用 Linux系统中的Shell是一个特殊的应用程序,它介于操作系统内核与用户之间&#x…...

力扣1038. 从二叉搜索树到更大和树(java,树的中序遍历解法)
Problem: 1038. 从二叉搜索树到更大和树 文章目录 题目描述思路解题方法复杂度Code 题目描述 给定一个二叉搜索树 root (BST),请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下, 二叉搜索树 满足下列约束条件ÿ…...
使用正则表达式来判断一个字符串只是否包含数字
使用正则表达式来判断一个字符串只是否包含数字 1、第一种 import java.util.regex.Pattern;public class Main {public static void main(String[] args) {String inputString "12345";if (containsOnlyDigits(inputString)) {System.out.println("字符串只…...
C#Wpf关于日志的相关功能扩展
目录 一、日志Sink(接收器) 二、Trace追踪实现日志 三、日志滚动 一、日志Sink(接收器) 安装NuGet包:Serilog Sink有很多种,这里介绍两种: Console接收器(安装Serilog.Sinks.Console); File接收器(安装…...

亚马逊云科技AI创新应用下的托管在AWS上的数据可视化工具—— Amazon QuickSight
目录 Amazon QuickSight简介 Amazon QuickSight的独特之处 Amazon QuickSight注册 Amazon QuickSight使用 Redshift和Amazon QuickSightt平台构建数据可视化应用程序 构建数据仓库 数据可视化 Amazon QuickSight简介 亚马逊QuickSight是一项可用于交付的云级商业智能 (BI…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...