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,是一种内存映射文件的技术。mmap可以将一个文件或者其它对象映射到进…...
深入了解云计算:发展历程、服务与部署模型、未来趋势与挑战
开篇博主 bluetata 的观点:PaaS 服务必将是未来10年云计算权重最高的趋势(05/02/2023 15:32) 文章目录 一、前言二、认识了解云计算2.1 什么是云计算2.1.1 维基百科上的云计算定义2.1.2 NIST 标准云计算定义2.1.3 如果被面试如何解释云计算 2…...
使用乐鑫 Web IDE 助力物联网开发
乐鑫 Web IDE 是基于 Eclipse Theia 的框架,支持 ESP-IDF VS Code 插件同时具备多项辅助工具。您可以观看我们在 Espressif DevCon22 上的演示视频,了解它的实际应用。 【乐鑫开发者大会-21】搭载 ESP-IDF Visual Studio Code 插件的乐鑫 …...
Maven(5)---Maven的部署和发布
Maven的部署和发布 在前面的博客中,我们已经学习了Maven的基础知识、依赖管理、插件和生命周期,以及多模块项目管理。本篇博客将介绍Maven的部署和发布功能。 什么是部署和发布 在软件开发过程中,部署和发布是非常重要的环节。部署是指将软…...
内网渗透之权限维持-黄金白银票据隐藏账户远控-RustDeskGotoHTTP
0x01权限维持-隐藏用户 CreateHiddenAccount工具 CreateHiddenAccount -u test -p Psswrd用户管理能查看到,命令查看看不到,单机版无法删除(不在任何组),域环境(在administrator组中)可以删除 0x02权限维持-黄金白银票据 ⻩⾦票据⽣成攻…...
动态规划——带权活动选择
带权活动选择Time Limit: 3000 MSMemory Limit: 1000 KB Description 给定n个活动,活动ai表示为一个三元组(si,fi,vi),其中si表示活动开始时间,fi表示活动的结束时间,vi表示活动的权重, si<fi。带权活动选择问题是选择一些活…...
软考A计划-真题-分类精讲汇总-第十八章(面向对象程序设计)
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…...
【C++ 入坑指南】(09)数组
文章目录 简介一维数组1. 定义2. 特点3. 用途4. 示例 二维数组1. 定义2. 用途3. 示例 简介 C 支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。 一维数组 1. 定义…...
Vue.js
文章目录 Vue(前端框架)data基本语法v-bind(属性)v-if(条件)v-formethods事件v-model表单绑定todolist(添加删除展示内容,含上下移动)es6语法生命周期函数axios发送ajax请…...
博士毕业答辩流程 注意事项
前言:2023年5月17日14:00-17:00,与实验室其他同学一起旁听了本实验室的博士论文答辩。接下来,我对博士毕业答辩的大致流程进行简要介绍,并对个环节的注意事项进行总结归纳,供毕业生参考。 目录 1. 准备阶段2. 汇报期间…...
拼多多开放平台订单详情接口解析
API接口订单接口是指用于实现订单相关操作的程序接口。通过这个接口,用户可以实现创建、修改、查询和取消订单等功能。 常见的API接口订单接口包括: 创建订单接口,用于实现用户下单操作。 修改订单接口,用于修改已有订单信息。 …...
如何把ipa文件(iOS安装包)安装到iPhone手机上? 附方法汇总
苹果APP安装包ipa如何安装在手机上?很多人不知道怎么把ipa文件安装到手机上,这里就整理了苹果APP安装到iOS设备上的方式,仅供参考 苹果APP安装包ipa如何安装在手机上?使用过苹果手机的人应该深有感触,那就是苹果APP安…...
由浅入深了解 深度神经网络优化算法
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 导言 优化是从一组可用的备选方案中选择最佳方案。优化无疑是深度学习的核心。基于梯度下降的方法已经成为训练深度神经网络的既定方法。 在最简单的情况下,优化问题包括通过系统地从允许集合中…...
LIN-报文结构
文章目录 协议规范一、字节场二、报文头(HEADER FIELDS)同步间隔(synchronisation break)同步场(SYNCH FIELD)标识符场(IDENTIFIER FIELD) 三、数据场(DATE FIELDS)四、校…...
南京邮电大学通达学院2023c++实验报告(三)
题目 实验题目1 某公司财务部需要开发一个计算雇员工资的程序。该公司有3类员工,工资计算方式如下: (1)工人工资:每小时工资额(通过成员函数设定)乘以当月工作时数(通过成员函数设定),再加上工龄工资。 (2)销售员工资:每小时工资额(通过成员函数设定)乘以当月…...
ISO9000和ISO9001有哪些区别?
作为ISO标准体系的新手,ISO9000和ISO9001是第一个接触到的标准。有些人可能会含糊地表达包含关系的词语,但他们仍然无法真正理解它们。两者的关系是什么?有什么区别?事实上,两者的主要区别体现在以下三个方面: 第一&am…...
第7章异常、断言和曰志
Java和C异 在C中,throw说明符在运行时执行。Java在编译时执行。 处理错误 异常处理的任务就是将控制权从产生错误的地方转移到能够处理这种情况的错误处理器。 如果由于出现错误而使得某些操作没有完成,程序应该:返回到一种安全状态&#…...
springboot读取和写入csv文件数据
前言 csv格式的表格,和xls以及xlsx格式的表格有一些不同,不能够直接用处理xls的方式处理csv; 以下我将介绍如何读取并写入csv数据 准备工作 要处理csv格式的表格数据,我们首先需要引入pom.xml的依赖 <dependency><art…...
【产品经理】工作交接
一、前言 相信大家对这样的场景一定不陌生:有一天去找某个业务的负责人,突然被告知调岗了,或是辞职了,更坏的情况是,甚至完全找不到相关人员了,直接导致工作搁置了。这种情况,你应该多少会感到…...
Springer期刊 latex投稿经验分享
Springer Nature期刊的latex模板下载: Download the journal article template package 以MTAP为例(修改之后对修订稿的投递过程) 第一步:将您的文章提交到适当的期刊轨道或特刊。 如有必要,从下拉菜单中更改您提交的文章类型。 然后点击Proceed 第二步: 与您提交的先前修…...
Sentinel-3B OLCI 3 级全球分箱地球观测降分辨率(ERR)叶绿素(CHL)数据,版本 2022.0
Sentinel-3B OLCI Level-3 Global Binned Earth-observation Reduced Resolution (ERR) Chlorophyll (CHL) Data, version 2022.0 简介 叶绿素 a 数据集提供全球网格化的表层叶绿素 a 浓度(浮游植物生物量的替代指标)合成数据。CHL 支持时间序列和气候…...
华硕笔记本终极性能控制指南:用G-Helper完全替代Armoury Crate
华硕笔记本终极性能控制指南:用G-Helper完全替代Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zen…...
写论文的神助攻!好用的AI写作辅助软件,逻辑清晰质量高
作为一名刚完成毕业论文的过来人,我太懂写论文的痛苦了 —— 选题迷茫、文献浩如烟海、框架混乱、逻辑不清、反复修改、查重降重反复折腾... 直到我发现了这套 AI 写作工具组合,简直是论文写作的 "开挂神器",效率直接拉满ÿ…...
中兴光猫终极管理指南:解锁工厂模式与Telnet权限的实战教程
中兴光猫终极管理指南:解锁工厂模式与Telnet权限的实战教程 【免费下载链接】zteOnu A tool that can open ZTE onu device factory mode 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 掌握中兴光猫的设备管理和权限获取能力是网络管理员和技术爱好者…...
风控系统如何全维度识别爬虫:IP、账号与行为的协同决策机制
1. 这不是“反爬失败”,而是风控系统在对你做全维度画像你写完一段 requests BeautifulSoup 的代码,本地跑通了,开开心心部署到服务器,结果第二天早上发现:所有请求返回 403,日志里全是空响应;…...
多模型聚合平台如何助力网站AIB测试与选型
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 多模型聚合平台如何助力网站AIB测试与选型 对于网站产品经理而言,首页文案的生成质量直接影响用户的第一印象和转化率。…...
基于Max78000与规则引导的音频数据集构建:边缘AI声音识别实战
1. 项目概述:当边缘AI遇见棕榈树里的“窃听者”在边缘计算和物联网设备大行其道的今天,我们常常面临一个核心矛盾:一方面,我们希望设备足够“聪明”,能实时识别并响应特定的声音模式,比如工厂里高压阀门的异…...
Unity塔防底层架构:ScriptableObject驱动的数据契约设计
1. 这不是“又一个塔防模板”,而是塔防开发的底层操作系统我第一次在Asset Store点开Tower Defense Toolkit 4(TDTK-4)的预览图时,下意识划走了——界面太“干净”了,没有炫酷的粒子特效演示,没有满屏飞舞的…...
PS5 NOR Modifier深度解析:如何通过Windows工具修复PS5硬件故障与实现光驱版转数字版
PS5 NOR Modifier深度解析:如何通过Windows工具修复PS5硬件故障与实现光驱版转数字版 【免费下载链接】PS5NorModifier The PS5 Nor Modifier is an easy to use Windows based application to rewrite your PS5 NOR file. This can be useful if your NOR is corru…...
SpeakingURL版本升级指南:从旧版本迁移到最新版本的完整教程
SpeakingURL版本升级指南:从旧版本迁移到最新版本的完整教程 【免费下载链接】speakingurl Generate a slug – transliteration with a lot of options 项目地址: https://gitcode.com/gh_mirrors/sp/speakingurl SpeakingURL是一款强大的URL友好化工具&…...
