c++内存映射文件

概念

将一个文件直接映射到进程的进程空间中(“映射”就是建立一种对应关系,这里指硬盘上文件的位置与进程逻辑地址空间中一块相同区域之间一 一对应,这种关系纯属是逻辑上的概念,物理上是不存在的),这样可以通过内存指针用读写内存的办法直接存取文件内容。

特点

文件数据可以用内存读/写指令来访问,而不是用Read和Write这样的I/O系统函数,从而提高了文件存取速度。

流程

  • 打开文件,创建文件句柄;
  • 为文件创建内存映射内核对象,返回内存映射文件句柄;
  • 映射整个文件或一部分到进程的虚拟地址空间,返回文件映射到内存后的起始地址;
  • 解除文件映射;
  • 关闭内存映射文件句柄;
  • 关闭文件句柄;

函数

1)创建文件句柄。

  • windows
# 函数
HANDLE CreateFile(LPCTSTR lpFileName,           //普通文件名或者设备文件名
	DWORD dwDesiredAccess,                      //访问模式(写/读)
	DWORD dwShareMode,                          //共享模式
	LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针
	DWORD dwCreationDisposition,                //如何创建
	DWORD dwFlagsAndAttributes,                 //文件属性
	HANDLE hTemplateFile                        //用于复制文件句柄
);
  • linux
# 函数
int open(const char *pathname, int flags, mode_t mode);

2)创建内存映射内核对象。

  • windows
# 函数
HANDLE CreateFileMapping(
  HANDLE hFile,                                      // 文件句柄,填写 INVALID_HANDLE_VALUE
  LPSECURITY_ATTRIBUTES lpFileMappingAttributes,     // 安全描述符,填写 NULL             
  DWORD flProtect,                                   // 映射对象保护属性
  DWORD dwMaximumSizeHigh,                           // 文件映射的最大长度的高32位
  DWORD dwMaximumSizeLow,                            // 文件映射的最大长度的低32位
  LPCTSTR lpName                                     // 文件映射对象名称
);
  • linux
# 函数
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

# 参数说明
## start:映射区的开始地址
## length:映射区的长度
## prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
## flags:指定映射对象的类型,映射选项和映射页是否可以共享。
## fd:有效的文件描述词。如果MAP_ANONYMOUS被设定,为了兼容问题,其值应为-1
## offset:被映射对象内容的起点。

3)映射文件到进程的虚拟地址空间。

  • windows
# 函数
LPVOID MapViewOfFile(
  HANDLE hFileMappingObject,  // CreateFileMapping()返回的文件映像对象句柄
  DWORD dwDesiredAccess,      // 数据的访问方式
  DWORD dwFileOffsetHigh,     // 文件映射起始偏移的高32位
  DWORD dwFileOffsetLow,      // 文件映射起始偏移的低32位
  DWORD dwNumberOfBytesToMap  // 文件中要映射的字节数,为0表示映射整个文件映射对象
);

4)在接收进程中打开对应的内存映射对象。

# 函数
HANDLE OpenFileMapping(
  DWORD dwDesiredAccess,  // 数据的访问方式
  BOOL bInheritHandle,    // 是否继承句柄
  LPCTSTR lpName          // 要打开的文件映射对象名称
);

5)回写内存映射文件。

  • windows
# 函数
BOOL FlushViewOfFile(
	LPCVOID lpBaseAddress, // 开始的地址
	SIZE_T dwNumberOfBytesToFlush // 数据块的大小
);
  • linux
#include <sys/mman.h>

# 函数
int msync(void *addr, size_t length, int flags);

# 参数说明
## 内存段需要修改的部分作为参数传递过来的起始地址addr和长度len确定。
## flags 参数控制着执行修改的具体方式:
#### MS_ASYNC      采用异步写方式
#### MS_SYNC       采用同步写方式
#### MS_INVALIDATE 从文件中读回数据

6)解除文件映射。

  • windows
# 函数
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);

# 参数说明
## lpBaseAddress: 指向要取消映射的文件的映射视图基址的指针。此值必须与上一次调用 MapViewOfFile或 MapViewOfFileEx 函数返回的值相同。
  • linux
# 函数
int munmap(void * addr, size_t len);

# 参数说明
## addr:映射内存起始地址
## len: 欲取消的内存大小

# 返回值
执行成功时,munmap()返回0。失败时,munmap返回-1。

示例

  • windows实例
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <chrono>
#include <ctime>

using namespace std;

int main()
{
	// MyData为测试文件,大小为1G
	// linux可执行"truncate -s 1G MyData"命令生成大文件
	uint64_t start = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
	// 创建文件
	HANDLE hFile = CreateFile(L"D://MyData",
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		cout << " CreateFile fail" << endl;
		return -1;
	}

	// 创建一个文件映射内核对象
	HANDLE hFileMapping = CreateFileMapping(hFile,
		nullptr,
		PAGE_READWRITE,
		0,
		0,
		nullptr);
	if (nullptr == hFileMapping)
	{
		cout << "CreateFileMapping fail" << endl;
		CloseHandle(hFile);
		return -1;
	}

	// 将文件数据映射到进程的地址空间
	char* mapData = (char*)MapViewOfFile(hFileMapping,
		FILE_MAP_ALL_ACCESS,
		0,
		0,
		0);
	if (nullptr == mapData)
	{
		cout << "MapViewOfFile fail" << endl;
		CloseHandle(hFileMapping);
		CloseHandle(hFile);
		return -1;
	}

	// 数据拷贝
	char* myBuf = mapData;

	// 计算时间
	uint64_t end = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); 
	uint64_t duration = end - start;   // 微妙差
	cout << "duration:" << duration << endl;

	UnmapViewOfFile(myBuf);
	CloseHandle(hFileMapping);
	CloseHandle(hFile);

    system("pause");
    return 0;
}

执行结果:

1G的文件完成文件映射需要143微妙。

在这里插入图片描述

  • linux实例
#include <iostream>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <chrono>
#include <ctime>
using namespace std;

#define MY_FILE_PATH "./MyData"

size_t get_file_size(const char *file_path) 
{
    struct stat buf;
    if (stat(file_path, &buf) < 0) 
	{
        printf("%s[%d]:%s", __FUNCTION__, __LINE__, strerror(errno));
        return -1;
    }
    return buf.st_size;
}

int main()
{
    // 执行"truncate -s 1G MyData"命令生成大文件
	uint64_t start = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
	
    // 打开文件
	int fd = open(MY_FILE_PATH, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
    if (-1 == fd) 
	{
        cout << "open failed,error:" << strerror(errno) << endl;;
        return -1;
    }

    // 获取文件大小
    size_t filelen = get_file_size(MY_FILE_PATH);
    if (-1 == (int)filelen) 
	{
        cout << "get file size failed" << endl;
        return -1;
    }
    cout << "filesize = " << filelen << endl;
 
    // 开始映射
    void* result = mmap(0, filelen, 
                PROT_READ|PROT_WRITE, 
                MAP_SHARED, 
                fd, 0);
    if (result == (void *)-1) 
	{
        cout << "mmap failed,error:" << strerror(errno) << endl;
        return -1;
    }
	
	// 计算时间
	uint64_t end = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
	uint64_t duration = end - start;   // 微妙差
	cout << "duration:" << duration << endl; 
	
    // 取消文件映射
    munmap(result, filelen);
	
	// 关闭文件句柄
    close(fd);

	return 0;
}

执行结果:

# 1G文件完成映射耗时270微妙
[root@localhost debug.x64-linux]# ./testFileMapping
filesize = 1073741824
duration:270
[root@localhost debug.x64-linux]# 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【vue】路由的搭建以及嵌套路由

目的&#xff1a;学习搭建vue2项目基础的vue路由和嵌套路由 1.npm 安装 router npm install vue-router3.6.52.src下新建文件夹router文件夹以及文件index.js index.js import Vue from vue import VueRouter from "vue-router" import Home from ../views/Home.…

spring boot 多模块项目非启动模块的bean无法注入(问题记录)

之前有说我搭了一个多模块项目&#xff0c;往微服务升级&#xff0c;注入的依赖在zuodou-bean模块中&#xff0c;入jwt拦截&#xff0c; Knife4j ,分页插件等等&#xff0c;但是启动类在system中&#xff0c;看网上说在启动类上加SpringBootApplication注解默认扫描范围为自己…

《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(4)-Charles如何设置捕获会话

1.简介 前边几篇宏哥介绍了Charles界面内容以及作用。今天宏哥就讲解和分享如何设置Charles后&#xff0c;我们就可以愉快地捕获会话&#xff0c;进行抓包了。因为上一篇许多小伙伴看到宏哥的Charles可以分开看到request和response&#xff0c;而自己的却看不到&#xff0c;因…

【wifi模块选型指导】数据传输WiFi模块的选型参考_USB/UART接口WiFi模块

数据传输WiFi模块有USB接口和UART接口两大类&#xff0c;为满足行业客户的不同应用需求&#xff0c;SKYLAB研发推出了多款2.4GHz单频&#xff0c;2.4/5GHz双频的USB接口WiFi模块和UART接口WiFi模块&#xff0c;数据传输能力&#xff0c;传输距离各有不同。怎么选才是最适合的呢…

MySql如何卸载干净经验分享

第一步&#xff1a;首先打开注册表&#xff1a;点击电脑的开始按钮&#xff0c;打开找到运行&#xff0c;输入regedit&#xff0c;进入注册表&#xff1b; 第二步&#xff1a;删除mysql再注册表中的信息&#xff0c;以下三个目录&#xff1a; 1.HKEY_LOCAL_MACHINE\SYSTEM\Cont…

论文阅读—2023.7.13:遥感图像语义分割空间全局上下文信息网络(主要为unet网络以及改unet)附加个人理解与代码解析

前期看的文章大部分都是深度学习原理含量多一点&#xff0c;一直在纠结怎么改模型&#xff0c;论文看的很吃力&#xff0c;看一篇忘一篇&#xff0c;总感觉摸不到方向。想到自己是遥感专业&#xff0c;所以还是回归遥感影像去谈深度学习&#xff0c;回归问题&#xff0c;再想着…

CMS垃圾收集器三色标记-JVM(十二)

上篇文章说了CMS垃圾收集器是赋值清除&#xff0c;所以他不可以碎片整理&#xff0c;于是jvm支持两个参数&#xff0c;几次fullGC之后碎片整理压缩空间。Cms他会抢占cpu资源&#xff0c;因为是并行运行&#xff0c;所以会有浮动垃圾。还有执行不确定性&#xff0c;垃圾收集完&a…

企业需要一个数字体验平台(DXP)吗?

数字体验平台是一个软件框架&#xff0c;通过与不同的业务系统喝解决方案集成&#xff0c;帮助企业和机构建立、管理和优化跨渠道的数字体验。帮助企业实现跨网站、电子邮件、移动应用、社交平台、电子商务站点、物联网设备、数字标牌、POS系统等传播内容&#xff0c;除了为其中…

【ArcGIS Pro二次开发】(48):三调土地利用现状分类面积汇总统计

之前做了一个三调三大类面积统计&#xff0c;有小伙伴反映太粗糙&#xff0c;想要一个完整的地类面积汇总表。 【ArcGIS Pro二次开发】(35)&#xff1a;三调三大类面积统计 本质上并没有多少难度&#xff0c;之前也做过类似的用地用海汇总表&#xff0c;于是拿出来改一改就好了…

【已解决】天翼电信宽带改桥模式,使用路由器ppoe拨号

运营商在给办理宽带时会默认给宽带设置成光猫ppoe拨号&#xff0c;路由器只需设置为dhcp获取ip&#xff0c;插入到光猫的lan口即可上网。但运营商的光猫路由性能有限&#xff0c;会影响到网络体验。而将光猫设置为桥模式&#xff0c;使用路由器拨号&#xff0c;可以实现路由器进…

【C语言】深剖数据在内存中的存储

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在回炉重造C语言&#xff08;2023暑假&#xff09; ✈️专栏&#xff1a;【C语言航路】 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你…

酷开科技大屏营销,撬动营销新增量

5G、人工智能、元宇宙等技术的发展促使数字营销的内容、渠道、传播方式发生了一系列变化&#xff1b;存量竞争下&#xff0c;增长成为企业更加迫切、更具挑战的课题&#xff0c;品牌营销活动越来越围绕“生意增长”和“提效转化”的目标展开。 如今的市场环境下&#xff0c;产…

Nacos(服务注册与发现)+SpringBoot+openFeign项目集成

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我&#xff0c;不迷路 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术…

基础语言模型LLaMA

LLaMA包含从7B到65B参数的基础语言模型集合。Meta在数万亿个tokens上训练了模型&#xff0c;LLaMA-13B在大多数基准测试中优于GPT-3&#xff08;175B&#xff09;。 来自&#xff1a;LLaMA: Open and Efficient Foundation Language Models 目录 背景概述方法预训练数据架构Op…

openGauss学习笔记-09 openGauss 简单数据管理-创建数据库

文章目录 openGauss学习笔记-09 openGauss 简单数据管理-创建数据库9.1 语法格式9.2 参数说明9.3 示例 openGauss学习笔记-09 openGauss 简单数据管理-创建数据库 数据库安装完成后&#xff0c;默认生成名称为postgres的数据库。您需要自己创建一个新的数据库。 9.1 语法格式…

Appium+python自动化(十一)- 元素定位- 下卷超详解)

1、 List定位 List故名思义就是一个列表&#xff0c;在python里面也有list这一个说法&#xff0c;如果你不是很理解什么是list&#xff0c;这里暂且理解为一个数组或者说一个集合。首先一个list是一个集合&#xff0c;那么他的个数也就成了不确定性&#xff0c;所以这里需要用复…

C\C++ 使用exception类,抛出自定义异常并捕获

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan 简介&#xff1a; 抛出异常&#xff0c;并捕获 exception 效果&#xff1a; 代码&#xff1a; #include <iostream> #include <exception> #include <stdexcept&g…

C# OpenCvSharp+DlibDotNet 人脸替换 换脸

效果 Demo下载 项目 VS2022.net4.8OpenCvSharp4DlibDotNet 相关介绍参考 代码 using DlibDotNet; using OpenCvSharp.Extensions; using OpenCvSharp; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Dra…

和为 K 的子数组——前缀和+哈希

题目链接&#xff1a;力扣 注意&#xff1a;此题不能使用滑动窗口&#xff0c;因为数组中可能会出现负数。也就是说右指针向后移1位不能保证区间会增大&#xff0c;左指针向后移1位也不能保证区间和会减小。给定左右指针的位置没有二段性 已知sum[i]是从nums[0~i]的和&#x…

实现小程序商城首页【源码公开】

效果图 页面源码 <view class"index-container"><view class"header"><!--搜索框【仅样式&#xff0c;不做处理】 start--><van-search bindtap"clickSearch" disabled shape"round" background"#9c7bf0&q…