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

Linux下对mmap封装使用

Linux下对mmap封装使用

  • 1、mmap简介
  • 2、Linux下mmap使用介绍
    • 2.1、mmap函数
    • 2.2、munmap函数
  • 3、对mmap进行封装
  • 4、对封装类MEM_MAP进行测试
  • 5、mmap原理
  • 6、源代码下载

1、mmap简介

mmap即memory map,是一种内存映射文件的技术。mmap可以将一个文件或者其它对象映射到进程的地址空间,进而实现磁盘地址和进程虚拟地址的一一对应关系。通过使用mmap技术,我们可以让不同进程通过映射到同一个普通文件的方式实现共享内存,普通文件被映射到进程地址空间当中之后,进程可以向访问普通内存一样对文件高效地进行一系列操作。

2、Linux下mmap使用介绍

2.1、mmap函数

mmap() 必须以 PAGE_SIZE(默认为4KB) 为单位进行映射,而内存也只能以页为单位进行映射,若要映射非 PAGE_SIZE 整数倍的地址范围,要先进行内存对齐,强行以 PAGE_SIZE 的倍数大小进行映射。函数声明如下:

#include <sys/mman.h>
void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);

参数说明:

  • addr: 映射区的开始地址,设置为0时表示由系统决定映射区的起始地址
  • length: 映射区的长度,长度单位是以字节为单位,不足一内存页按一内存页处理
  • port: 映射区域的权限,不能与文件的打开模式冲突,可以通过or运算合理地组合在一起
  • flags: 映射的标志位,可以通过or运算合理地组合在一起
  • fd: 有效的文件描述词,一般是由open()函数返回
  • offset: 文件偏移量

参数 port 的取值如下:

PORT_EXEC:映射区具有可执行权限
PROT_READ:映射区具有可读权限
PROT_WRITE:映射区具有可写权限
PROT_NONE:映射区不可被访问

参数 flags 的取值如下:

MAP_SHARED:对映射区域的写入操作直接反映到文件当中
MAP_FIXED:若在start上无法创建映射则失败(如果没有此标记会自动创建)
MAP_PRIVATE:对映射区域的写入操作只反映到缓冲区当中不会写入到真正的文件
MAP_ANONYMOUS:匿名映射将虚拟地址映射到物理内存而不是文件(忽略fd)
MAP_DENYWRITE:拒绝其它文件的写入操作
MAP_LOCKED:锁定映射区域保证其不被置换

返回值:成功执行时,mmap() 返回被映射区的指针。失败时,mmap() 返回 MAP_FAILED(其值为(void *)-1),并且 errno 被设为以下的某个值

EACCES:访问出错
EAGAIN:文件已被锁定,或者太多的内存已被锁定
EBADF:fd不是有效的文件描述词
EINVAL:一个或者多个参数无效
ENFILE:已达到系统对打开文件的限制
ENODEV:指定文件所在的文件系统不支持内存映射
ENOMEM:内存不足,或者进程已超出最大内存映射数量
EPERM:权能不足,操作不允许
ETXTBSY:已写的方式打开文件,同时指定 MAP_DENYWRITE 标志
SIGSEGV:试着向只读区写入
SIGBUS:试着访问不属于进程的内存区

2.2、munmap函数

munmap() 声明如下:

#include <sys/mman.h>
int munmap(void* start, size_t length);

参数说明:

  • start: 映射区的指针,即mmap()的返回值
  • length: 映射区的长度

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

3、对mmap进行封装

下面给出 MEM_MAP 类的设计:

#ifndef __MEM_MAP_H
#define __MEM_MAP_H#include <iostream>
#include <string>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>class Noncopyable
{
public:Noncopyable() = default;~Noncopyable() = default;Noncopyable(const Noncopyable&) = delete;Noncopyable& operator=(const Noncopyable&) = delete;
};#define MAX_PATH_LEN    200class MEM_MAP : private Noncopyable
{
public:MEM_MAP();~MEM_MAP();//取消映射void unmap();//取消映射并删除对应文件void remove();//映射指定的文件int map(const char* filename,size_t length,int flags = O_RDWR | O_CREAT,mode_t mode = 0644,int prot = PROT_READ | PROT_WRITE,int share = MAP_SHARED,void* addr = NULL,off_t offset = 0);public://将数据立即刷到文件里(MS_ASYNC、MS_SYNC、MS_INVALIDATE)int sync(size_t len, int flags = MS_SYNC);int sync(int flags = MS_SYNC);public://返回基地址void* addr() const;//返回映射大小size_t size() const;//返回文件描述符int fd() const;//返回文件名const char* filename() const;private://mmap基地址void* m_addr;//mmap大小size_t m_length;//mmap文件描述符int m_fd;//mmap文件名char m_filename[MAX_PATH_LEN];
};#endif /*__MEM_MAP_H*/

以下是 MEM_MAP 类各个方法的具体实现:

#include "mem_map.h"MEM_MAP::MEM_MAP(): m_addr(NULL),m_length(0),m_fd(-1)
{memset(m_filename, 0, sizeof(m_filename));
}MEM_MAP::~MEM_MAP()
{unmap();
}void MEM_MAP::unmap()
{if (m_addr != NULL){munmap(m_addr, m_length);}if (m_fd != -1){close(m_fd);}m_addr = NULL;m_length = 0;m_fd = -1;memset(m_filename, 0, sizeof(m_filename));
}void MEM_MAP::remove()
{char filename[MAX_PATH_LEN];strncpy(filename, m_filename, MAX_PATH_LEN);unmap();if (filename[0] != '\0'){unlink(filename);}
}int MEM_MAP::map(const char* filename,size_t length,int flags,mode_t mode,int prot,int share,void* addr,off_t offset)
{//取消旧的映射unmap();//数据赋值m_length = length;strncpy(m_filename, filename, MAX_PATH_LEN);//打开文件描述符m_fd = open(m_filename, flags, mode);if (m_fd == -1){std::cout << strerror(errno) << std::endl;unmap();return -1;}//指定文件大小if (truncate(m_filename, m_length) == -1){std::cout << strerror(errno) << std::endl;unmap();return -2;}//建立映射m_addr = mmap(addr, length, prot, share, m_fd, offset);if (m_addr == MAP_FAILED){std::cout << strerror(errno) << std::endl;m_addr = NULL;unmap();return -3;}return 0;
}int MEM_MAP::sync(size_t len, int flags)
{return msync(m_addr, len, flags);
}int MEM_MAP::sync(int flags)
{return msync(m_addr, m_length, flags);
}void* MEM_MAP::addr() const
{return m_addr;
}size_t MEM_MAP::size() const
{return m_length;
}int MEM_MAP::fd() const
{return m_fd;
}const char* MEM_MAP::filename() const
{return m_filename;
}

4、对封装类MEM_MAP进行测试

测试代码如下,运行之后会生成一个拥有315行 Hello World! 的文件,且末尾会剩余一个字节

#include "mem_map.h"int main(int argc, char* argv[])
{MEM_MAP mmap;if (mmap.map("test.mmap", 4 * 1024) != 0){return -1;}char* str = (char*)mmap.addr();while (1){if (strlen(str) + strlen("Hello World!\n") > mmap.size()){break;}strcat(str, "Hello World!\n");}return 0;
}

5、mmap原理

mmap实现内存映射的过程主要分为以下三个阶段:

1. 创建映射区域

过程:进程在用户空间调用 mmap() ,此时进程会在当前进程的地址空间当中寻找一段连续的空闲虚拟地址,并给这块虚拟地址分配一个 vm_area_struct 结构(会自动对各个区域进行初始化),然后将新键的虚拟结构插入到虚拟地址空间的链表或者红黑树当中。

2. 实现物理内存地址和虚拟地址的映射关系

过程:通过待映射的文件描述符指针,在文件描述符表当中找到对应的文件描述符链接到内核已经打开的文件描述符集当中的 struct_file,这个 struct_file 维护着这个被打开的文件的各项信息,通过这个文件的结构体链接到 file_operations,调用内核的mmap函数(原型为 int mmap(struct file* filp, struct vm_area_struct* vma),注意这个不是用户态的mmap),内核mmap函数通过虚拟文件系统当中的inode定位到文件的物理地址,通过 reamp_pfn_range() 建立页表即实现了文件地址和虚拟地址的映射关系。

3. 实现虚拟地址上的数据同步到磁盘文件中

过程:进程的读或写操作访问虚拟地址空间这一段映射地址,通过查询页表,发现这一段地址并不在物理页面上,因为目前只建立了地址映射,真正的硬盘数据还没有拷贝到内存中,因此引发缺页异常。缺页异常进行一系列判断,确定无非法操作后,内核发起请求调页过程。调页过程先在交换缓存空间(swap cache)中寻找需要访问的内存页,如果没有则调用 nopage() 把所缺的页从磁盘装入到主存中,之后进程即可对这片主存进行读或者写的操作,如果写操作改变了其内容,一定时间后系统会自动回写脏页面到对应磁盘地址(由 flags 参数决定是否会自动回写),即完成了写入到文件的过程。

6、源代码下载

下载地址:mmap封装测试代码

相关文章:

Linux下对mmap封装使用

Linux下对mmap封装使用 1、mmap简介2、Linux下mmap使用介绍2.1、mmap函数2.2、munmap函数 3、对mmap进行封装4、对封装类MEM_MAP进行测试5、mmap原理6、源代码下载 1、mmap简介 mmap即memory map&#xff0c;是一种内存映射文件的技术。mmap可以将一个文件或者其它对象映射到进…...

深入了解云计算:发展历程、服务与部署模型、未来趋势与挑战

开篇博主 bluetata 的观点&#xff1a;PaaS 服务必将是未来10年云计算权重最高的趋势&#xff08;05/02/2023 15:32&#xff09; 文章目录 一、前言二、认识了解云计算2.1 什么是云计算2.1.1 维基百科上的云计算定义2.1.2 NIST 标准云计算定义2.1.3 如果被面试如何解释云计算 2…...

使用乐鑫 Web IDE 助力物联网开发

乐鑫 Web IDE 是基于 Eclipse Theia 的框架&#xff0c;支持 ESP-IDF VS Code 插件同时具备多项辅助工具。您可以观看我们在 Espressif DevCon22 上的演示视频​​​​​​​&#xff0c;了解它的实际应用。 【乐鑫开发者大会-21】搭载 ESP-IDF Visual Studio Code 插件的乐鑫 …...

Maven(5)---Maven的部署和发布

Maven的部署和发布 在前面的博客中&#xff0c;我们已经学习了Maven的基础知识、依赖管理、插件和生命周期&#xff0c;以及多模块项目管理。本篇博客将介绍Maven的部署和发布功能。 什么是部署和发布 在软件开发过程中&#xff0c;部署和发布是非常重要的环节。部署是指将软…...

内网渗透之权限维持-黄金白银票据隐藏账户远控-RustDeskGotoHTTP

0x01权限维持-隐藏用户 CreateHiddenAccount工具 CreateHiddenAccount -u test -p Psswrd用户管理能查看到&#xff0c;命令查看看不到&#xff0c;单机版无法删除(不在任何组)&#xff0c;域环境(在administrator组中)可以删除 0x02权限维持-黄金白银票据 ⻩⾦票据⽣成攻…...

动态规划——带权活动选择

带权活动选择Time Limit: 3000 MSMemory Limit: 1000 KB Description 给定n个活动&#xff0c;活动ai表示为一个三元组(si,fi,vi)&#xff0c;其中si表示活动开始时间&#xff0c;fi表示活动的结束时间&#xff0c;vi表示活动的权重, si<fi。带权活动选择问题是选择一些活…...

软考A计划-真题-分类精讲汇总-第十八章(面向对象程序设计)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…...

【C++ 入坑指南】(09)数组

文章目录 简介一维数组1. 定义2. 特点3. 用途4. 示例 二维数组1. 定义2. 用途3. 示例 简介 C 支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。 一维数组 1. 定义…...

Vue.js

文章目录 Vue&#xff08;前端框架&#xff09;data基本语法v-bind&#xff08;属性&#xff09;v-if&#xff08;条件&#xff09;v-formethods事件v-model表单绑定todolist&#xff08;添加删除展示内容&#xff0c;含上下移动&#xff09;es6语法生命周期函数axios发送ajax请…...

博士毕业答辩流程 注意事项

前言&#xff1a;2023年5月17日14:00-17:00&#xff0c;与实验室其他同学一起旁听了本实验室的博士论文答辩。接下来&#xff0c;我对博士毕业答辩的大致流程进行简要介绍&#xff0c;并对个环节的注意事项进行总结归纳&#xff0c;供毕业生参考。 目录 1. 准备阶段2. 汇报期间…...

拼多多开放平台订单详情接口解析

API接口订单接口是指用于实现订单相关操作的程序接口。通过这个接口&#xff0c;用户可以实现创建、修改、查询和取消订单等功能。 常见的API接口订单接口包括&#xff1a; 创建订单接口&#xff0c;用于实现用户下单操作。 修改订单接口&#xff0c;用于修改已有订单信息。 …...

如何把ipa文件(iOS安装包)安装到iPhone手机上? 附方法汇总

苹果APP安装包ipa如何安装在手机上&#xff1f;很多人不知道怎么把ipa文件安装到手机上&#xff0c;这里就整理了苹果APP安装到iOS设备上的方式&#xff0c;仅供参考 苹果APP安装包ipa如何安装在手机上&#xff1f;使用过苹果手机的人应该深有感触&#xff0c;那就是苹果APP安…...

由浅入深了解 深度神经网络优化算法

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 导言 优化是从一组可用的备选方案中选择最佳方案。优化无疑是深度学习的核心。基于梯度下降的方法已经成为训练深度神经网络的既定方法。 在最简单的情况下&#xff0c;优化问题包括通过系统地从允许集合中…...

LIN-报文结构

文章目录 协议规范一、字节场二、报文头&#xff08;HEADER FIELDS&#xff09;同步间隔&#xff08;synchronisation break)同步场&#xff08;SYNCH FIELD&#xff09;标识符场&#xff08;IDENTIFIER FIELD&#xff09; 三、数据场&#xff08;DATE FIELDS&#xff09;四、校…...

南京邮电大学通达学院2023c++实验报告(三)

题目 实验题目1 某公司财务部需要开发一个计算雇员工资的程序。该公司有3类员工,工资计算方式如下: (1)工人工资:每小时工资额(通过成员函数设定)乘以当月工作时数(通过成员函数设定),再加上工龄工资。 (2)销售员工资:每小时工资额(通过成员函数设定)乘以当月…...

ISO9000和ISO9001有哪些区别?

作为ISO标准体系的新手&#xff0c;ISO9000和ISO9001是第一个接触到的标准。有些人可能会含糊地表达包含关系的词语&#xff0c;但他们仍然无法真正理解它们。两者的关系是什么&#xff1f;有什么区别&#xff1f;事实上&#xff0c;两者的主要区别体现在以下三个方面: 第一&am…...

第7章异常、断言和曰志

Java和C异 在C中&#xff0c;throw说明符在运行时执行。Java在编译时执行。 处理错误 异常处理的任务就是将控制权从产生错误的地方转移到能够处理这种情况的错误处理器。 如果由于出现错误而使得某些操作没有完成&#xff0c;程序应该&#xff1a;返回到一种安全状态&#…...

springboot读取和写入csv文件数据

前言 csv格式的表格&#xff0c;和xls以及xlsx格式的表格有一些不同&#xff0c;不能够直接用处理xls的方式处理csv&#xff1b; 以下我将介绍如何读取并写入csv数据 准备工作 要处理csv格式的表格数据&#xff0c;我们首先需要引入pom.xml的依赖 <dependency><art…...

【产品经理】工作交接

一、前言 相信大家对这样的场景一定不陌生&#xff1a;有一天去找某个业务的负责人&#xff0c;突然被告知调岗了&#xff0c;或是辞职了&#xff0c;更坏的情况是&#xff0c;甚至完全找不到相关人员了&#xff0c;直接导致工作搁置了。这种情况&#xff0c;你应该多少会感到…...

Springer期刊 latex投稿经验分享

Springer Nature期刊的latex模板下载: Download the journal article template package 以MTAP为例(修改之后对修订稿的投递过程) 第一步:将您的文章提交到适当的期刊轨道或特刊。 如有必要,从下拉菜单中更改您提交的文章类型。 然后点击Proceed 第二步: 与您提交的先前修…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...