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

Linux- 内存映射文件(Memory-Mapped File)

内存映射文件(Memory-Mapped File)是⼀种将文件内容映射到内存中的机制,允许程序直接访问文件数据,就好像这些数据已经被加载到了内存⼀样。这个机制允许文件的内容被映射到⼀个进程的地址空间,从而允许程序以⼀种更高效的方式读取或写入文件数据,同时,多个进程可以映射同⼀个文件,从而实现进程间的数据共享。这对于进程间通信非常有用。

mmap()

mmap() 是一个Unix和Linux系统调用,用于在进程的地址空间中映射文件或设备,或者创建匿名内存映射。它提供了一种在文件和进程的内存之间建立直接映射的机制。这意味着对于映射的内存区域的任何修改都将直接反映到底层的文件中,反之亦然。

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

以下是 mmap() 函数的基本参数和它们的描述:

  1. 起始地址:

    • 希望映射开始的内存地址。通常设置为 NULL,让系统决定最佳起始地址。
  2. 长度:

    • 要映射的文件或设备的字节数。
  3. 保护:

    • 映射区域的访问权限。常见的权限包括:
      • PROT_READ: 数据可以被读取。
      • PROT_WRITE: 数据可以被写入。
      • PROT_EXEC: 数据可以被执行。
      • PROT_NONE: 数据不能被访问。
  4. 标志:

    • 描述映射的类型和属性。常见的标志包括:
      • MAP_SHARED: 更改会反映到底层文件或其他映射此文件的进程中。
      • MAP_PRIVATE: 创建一个私有的映射,更改不会写回底层文件。
      • MAP_ANONYMOUSMAP_ANON: 创建一个匿名映射,不与任何文件关联。
      • MAP_FIXED: 使用指定的起始地址,如果该地址不可用,映射会失败。
  5. 文件描述符:

    • 要映射的文件或设备的描述符。如果使用 MAP_ANONYMOUS,则此值可以设置为 -1
  6. 偏移:

    • 从文件或设备的哪个位置开始映射。通常,这是以页面大小为单位的,所以通常将偏移量设置为系统页面大小的倍数。

成功调用 mmap() 会返回新映射区域的地址。如果调用失败,则返回 MAP_FAILED,并在 errno 中设置一个错误代码。

几点注意事项:

  • 使用 mmap() 创建的映射应当在不再需要时使用 munmap() 释放。
  • 当映射文件时,文件的长度应该大于或等于要映射的长度。可以使用 ftruncate() 调整文件大小。
  • 写入映射区域超出文件当前大小的部分可能会导致段错误。
  • 对于 MAP_SHARED 映射,更改将写回底层文件,但不一定立即写回。可以使用 msync() 来确保更改被同步到文件。

总的来说,mmap() 是一种强大而灵活的机制,用于文件I/O和进程间通信。

munmap()

munmap() 是一个Unix和POSIX系统调用,用于取消映射一个之前通过 mmap() 映射到进程地址空间的内存区域。映射的内存区域可能是文件的映射、匿名内存或其他类型的内存对象。

当我们不再需要访问一个内存映射或当进程完成其操作并想释放资源时,应该调用 munmap() 来取消映射。

以下是 munmap() 的基本参数和它们的描述:

  1. 地址 (addr):

    • 要取消映射的内存区域的起始地址。这应该是之前 mmap() 调用的返回值。
  2. 长度 (length):

    • 要取消映射的内存区域的长度(以字节为单位)。

函数的基本原型如下:

int munmap(void *addr, size_t length);

返回值:

  • 成功时,munmap() 返回 0
  • 失败时,返回 -1,并设置全局变量 errno 以指示错误原因。

一些常见的使用场景和注意事项:

  • 资源管理:

    • 在不需要访问映射内存区域时,应及时使用 munmap() 释放资源。否则,这可能会导致资源泄漏,尤其是在长时间运行的程序中。
  • 访问已取消映射的内存:

    • 一旦使用 munmap() 取消映射了一个内存区域,任何尝试访问该区域的操作都将导致未定义的行为,通常是段错误 (segmentation fault)。
  • 映射边界:

    • 当取消映射一个内存区域时,必须确保 addrlength 正确地对应于原始 mmap() 调用的值。尝试部分取消映射或使用不正确的地址和长度可能导致错误。
  • 与其他资源的关联:

    • 取消映射并不意味着与该映射相关的其他资源也被释放。例如,如果映射了一个文件,munmap() 只会取消映射,但不会关闭文件。我们仍然需要使用 close() 系统调用来关闭文件。

总的来说,munmap() 是内存映射管理的重要部分,正确地使用它可以帮助避免资源泄漏和确保程序的稳定性。在设计使用内存映射的应用程序时,我们应该始终确保在不再需要映射的时候调用 munmap() 来释放资源。

ftruncate()

ftruncate() 是一个系统调用,用于调整/设置已打开的文件的大小。这个调用可以使文件变大或变小。当文件增大时,新增的部分会被视为“空洞”,并且会读取为零字节;当文件缩小时,超出指定长度的部分将被丢弃。

以下是 ftruncate() 的基本参数和它们的描述:

  1. 文件描述符 (fd):

    • 这是要调整大小的文件的文件描述符。通常,这是使用 open() 或其他相关系统调用获得的。
  2. 长度 (length):

    • 这是要设置的文件的新大小,以字节为单位。

函数的基本原型如下:

int ftruncate(int fd, off_t length);

返回值:

  • 成功时,ftruncate() 返回 0
  • 失败时,返回 -1,并设置全局变量 errno 以指示错误原因。

一些常见的使用场景和注意事项:

  • 内存映射: 在使用 mmap() 创建文件的内存映射之前,如果想映射的部分超过了文件的当前大小,可以使用 ftruncate() 来增加文件的大小。

  • 数据库和日志文件: 数据库系统或日志文件管理系统可能会预先分配大块的磁盘空间以提高效率,而不是每次需要时都增加文件大小。这可以通过 ftruncate() 实现。

  • 文件截断: 如果只想保留文件的前部分并删除其余部分,ftruncate() 可以很容易地做到这一点。

  • 空洞文件: 在某些文件系统上,ftruncate() 可以用于创建所谓的“空洞文件”,这是一个包含未初始化数据(空洞)的文件,这些数据在磁盘上不占用任何空间,但在读取时会返回零字节。

总的来说,ftruncate() 是一个有用的系统调用,尤其是在需要精细控制文件大小或预分配磁盘空间的应用中。

示例

在下面的例子中,我们使用了两个 POSIX 信号量:sem_parent和sem_child来控制两个进程之间的同步。父进程首先写入消息然后通过sem_post通知子进程。子进程在收到消息并处理完后,通过sem_post通知父进程。这种方式确保了两个进程的同步,并且避免了忙等待。

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <semaphore.h>#define FILE_PATH "shared_memory_file"
#define FILE_SIZE 1024
#define SEM_PARENT "/sem_parent"
#define SEM_CHILD "/sem_child"int main() {int fd;char *shared_mem;// Create a filefd = open(FILE_PATH, O_RDWR | O_CREAT, 0777);if (fd == -1) {perror("open");return 1;}// Set the file sizeftruncate(fd, FILE_SIZE);// Map the file into memoryshared_mem = (char *)mmap(NULL, FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (shared_mem == MAP_FAILED) {perror("mmap");return 1;}// Create semaphoressem_t *sem_parent = sem_open(SEM_PARENT, O_CREAT, 0666, 0);sem_t *sem_child = sem_open(SEM_CHILD, O_CREAT, 0666, 0);pid_t pid = fork();if (pid == 0) { // Childsem_wait(sem_parent); // Wait for parent signalprintf("[Child] Received: %s\n", shared_mem);// Reply to the parentstrcpy(shared_mem, "Message received by child!");printf("[Child] Replied to parent.\n");sem_post(sem_child); // Signal the parent} else if (pid > 0) { // Parentstrcpy(shared_mem, "Hello from parent!");sem_post(sem_parent); // Signal the child// Wait for child signalsem_wait(sem_child);printf("[Parent] Message from child: %s\n", shared_mem);wait(NULL); // Wait for child to finish} else {perror("fork");return 1;}// Cleanupmunmap(shared_mem, FILE_SIZE);close(fd);unlink(FILE_PATH);sem_close(sem_parent);sem_close(sem_child);sem_unlink(SEM_PARENT);sem_unlink(SEM_CHILD);return 0;
}

程序运行结果如下:

majn@tiger:~/C_Project/mmap_project$ ./mmap_demo 
[Child] Received: Hello from parent!
[Child] Replied to parent.
[Parent] Message from child: Message received by child!

对于超出映射区域的内存访问,结果是不确定的,通常会导致错误。

当尝试访问超出我们通过mmap分配的映射区域的内存地址时,实际上是在访问进程地址空间中的非法地址。这通常会产生一个SIGSEGV信号,该信号表示段违规错误,即“segmentation fault”。

简而言之:

  1. 试图读取超出文件长度但在映射区域内的地址:通常会读到0,这是因为文件被视为以0字节填充直到映射的大小。

  2. 试图访问超出映射区域的地址:通常会导致段违规错误(segmentation fault)。

因此,最好确保只访问映射的内存区域内的地址,避免超出这个范围,以防止未定义的行为和潜在的程序崩溃。

相关文章:

Linux- 内存映射文件(Memory-Mapped File)

内存映射文件&#xff08;Memory-Mapped File&#xff09;是⼀种将文件内容映射到内存中的机制&#xff0c;允许程序直接访问文件数据&#xff0c;就好像这些数据已经被加载到了内存⼀样。这个机制允许文件的内容被映射到⼀个进程的地址空间&#xff0c;从而允许程序以⼀种更高…...

李航老师《统计学习方法》第五章阅读笔记

决策树&#xff08;decision tree&#xff09;是一种基本的分类与回归方法。本章主要讨论用于分类的决策树。决策树模型呈树形结构&#xff0c;在分类问题中&#xff0c;表示基于特征对实例进行分类的过程。 以下是关于分类决策树的一些基本概念和特点&#xff1a; 树形结构&am…...

iOS16新特性:实时活动-在锁屏界面实时更新APP消息 | 京东云技术团队

简介 之前在 《iOS16新特性:灵动岛适配开发与到家业务场景结合的探索实践》 里介绍了iOS16新的特性&#xff1a;实时更新&#xff08;Live Activity&#xff09;中灵动岛的适配流程&#xff0c;但其实除了灵动岛的展示样式&#xff0c;Live Activity还有一种非常实用的应用场景…...

使用 Elasticsearch、OpenAI 和 LangChain 进行语义搜索

在本教程中&#xff0c;我将引导您使用 Elasticsearch、OpenAI、LangChain 和 FastAPI 构建语义搜索服务。 LangChain 是这个领域的新酷孩子。 它是一个旨在帮助你与大型语言模型 (LLM) 交互的库。 LangChain 简化了与 LLMs 相关的许多日常任务&#xff0c;例如从文档中提取文本…...

NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061

今天发现,有两个处理器,启动以后,数据流不过去,后来,锁定问题在,queue队列上面,因为别的队列都可以通过,右键,empty queue清空,就是 这个队列不行,这个队列无法被删除,至于为什么导致这样的, 猜测是因为之前,流程设计好以后,队列没有设置背压,也没有设置队列中的内容大小和fl…...

leetcode20. 有效的括号 [简单题]

题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型…...

ubuntu20.04下源码编译colmap

由于稠密重建需要CUDA&#xff0c;因此先安装CUDA&#xff0c;我使用的是3050GPU&#xff0c;nvidia-smi显示最高支持CUDA11.4。 不要用sudo apt安装&#xff0c;版本较低&#xff0c;30系显卡建议安装CUDA11.0以上&#xff0c;这里安装了11.1版本。 下载&#xff1a; cuda_1…...

Jumpserver堡垒机

一、堡垒机概述 1、堡垒机的基本概念 堡垒机也是一台服务器&#xff0c;在一个特定的网络环境下&#xff0c;为了保障网络和数据不受来自外部和内部用户的入侵和破坏&#xff0c;而运用各种技术手段实时收集、监控网络环境中每一个组成部分&#xff08;服务器&#xff09;的系…...

第一百五十三回 如何实现滑动窗口

文章目录 概念介绍实现方法示例代码 我们在上一章回中介绍了自定义组件实现游戏摇杆相关的内容&#xff0c;本章回中将介绍 如何实现滑动窗口.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在本章回中介绍的滑动窗口表示在屏幕底部向上滑动时弹出一个窗口&a…...

Oracle 12c自动化管理特性的新进展:自动备份、自动恢复和自动维护功能的优势|oracle 12c相对oralce 11g的新特性(3)

一、前言: 前面几期讲解了oracle 12c多租户的使用、In-Memory列存储来提高查询性能以及数据库的克隆、全局数据字典和共享数据库资源的使用 今天我们讲讲oracle 12c的另外的一个自动化管理功能新特性:自动备份、自动恢复、自动维护的功能 二、自动备份、自动恢复、自动维护…...

Redis——Jedis中hash类型使用

hset 和 hget hset可以逐一添加key和value&#xff0c;也可以通过map类型来直接添加多组fields 而hget则返回string类型&#xff0c;如果元素不存在则返回null private static void hsetAndHget(Jedis jedis) {jedis.flushAll();jedis.hset("key", "f1"…...

肖sir__项目实战讲解__004

项目实战讲解 一、项目的类型 金融类&#xff1a; 保险(健康险理财险)、证券、基金(股票型基金、混合型基金、指数型基金、债券型基金、 天天基金网&#xff08;ETF基金、货币型基金、量化基金)、银行、贷款、信用卡、外汇、二元期权、期货原油、blockchain、 数字货币、黄金白…...

数据库数据恢复-ORACLE常见故障有哪些?恢复数据的可能性高吗?

ORACLE数据库常见故障&#xff1a; 1、ORACLE数据库无法启动或无法正常工作。 2、ORACLE数据库ASM存储破坏。 3、ORACLE数据库数据文件丢失。 4、ORACLE数据库数据文件部分损坏。 5、ORACLE数据库DUMP文件损坏。 ORACLE数据库数据恢复可能性分析&#xff1a; 1、ORACLE数据库无…...

合规性管理如何帮助产品团队按时交付?

成功的产品和产品发布背后通常需要经过一个涉及多个监督机构、多功能团队和利益相关者的复杂流程。在组织的治理、风险管理和合规性&#xff08;GRC&#xff09;框架下&#xff0c;产品团队不仅需要追求市场创新&#xff0c;还需要确保符合所有适用的法规、标准和合同要求。由于…...

从平均数到排名算法

平均数用更少的数字&#xff0c;概括一组数字。属于概述统计量、集中趋势测度、位置测度。中位数是第二常见的概述统计量。许多情况下比均值更合适。算术平均数是3中毕达哥拉斯平均数之一&#xff0c;另外两种毕达哥拉斯平均数是几何平均数和调和平均数。 算术平均 A M 1 n ∑…...

如何使用ESP8266微控制器和Nextion显示器为Home Assistant展示温度传感器和互联网天气预报

第一部分&#xff1a;引言与项目概述 在智能家居领域&#xff0c;实时监控和显示环境数据已经成为了一个热门的话题。无论是室内温度、室外温度&#xff0c;还是游泳池的温度&#xff0c;都可以通过各种传感器轻松获取。但如何将这些数据以直观、美观的方式展现出来呢&#xf…...

阻塞队列-生产者消费者模型

阻塞队列介绍标准库阻塞队列使用基于阻塞队列的简单生产者消费者模型。实现一个简单型阻塞队列 &#xff08;基于数组实现&#xff09; 阻塞队列介绍 不要和之前学多线程的就绪队列搞混&#xff1b; 阻塞队列&#xff1a;也是一个队列&#xff0c;先进先出。带有特殊的功能 &…...

Vector Art - 矢量艺术

什么是矢量艺术&#xff1f; 矢量图形允许创意人员构建高质量的艺术作品&#xff0c;具有干净的线条和形状&#xff0c;可以缩放到任何大小。探索这种文件格式如何为各种规模的项目提供创造性的机会。 什么是矢量艺术作品? 矢量艺术是由矢量图形组成的艺术。这些图形是基于…...

ruoyi-nbcio增加flowable流程待办消息的提醒,并提供右上角的红字数字提醒(一)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 1、数据库表方面 在原来sys_notice修改基础上增加一个表叫sys_notice_send 表结构如下&#xff1a; DROP …...

数据结构:二叉树的基本概念

文章目录 1. 二叉树的定义2. 二叉树的特点3. 特殊二叉树斜树满二叉树完全二叉树 4. 二叉树的性质 1. 二叉树的定义 如果我们猜一个100以内的数字,该怎么猜才能理论最快呢? 第一种方式:从1,2一直猜到100, 反正数字都是100以内,总能猜到的 第二种方式:先猜50,如果比结果小,猜75…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...