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() 函数的基本参数和它们的描述:
-
起始地址:
- 希望映射开始的内存地址。通常设置为
NULL,让系统决定最佳起始地址。
- 希望映射开始的内存地址。通常设置为
-
长度:
- 要映射的文件或设备的字节数。
-
保护:
- 映射区域的访问权限。常见的权限包括:
PROT_READ: 数据可以被读取。PROT_WRITE: 数据可以被写入。PROT_EXEC: 数据可以被执行。PROT_NONE: 数据不能被访问。
- 映射区域的访问权限。常见的权限包括:
-
标志:
- 描述映射的类型和属性。常见的标志包括:
MAP_SHARED: 更改会反映到底层文件或其他映射此文件的进程中。MAP_PRIVATE: 创建一个私有的映射,更改不会写回底层文件。MAP_ANONYMOUS或MAP_ANON: 创建一个匿名映射,不与任何文件关联。MAP_FIXED: 使用指定的起始地址,如果该地址不可用,映射会失败。
- 描述映射的类型和属性。常见的标志包括:
-
文件描述符:
- 要映射的文件或设备的描述符。如果使用
MAP_ANONYMOUS,则此值可以设置为-1。
- 要映射的文件或设备的描述符。如果使用
-
偏移:
- 从文件或设备的哪个位置开始映射。通常,这是以页面大小为单位的,所以通常将偏移量设置为系统页面大小的倍数。
成功调用 mmap() 会返回新映射区域的地址。如果调用失败,则返回 MAP_FAILED,并在 errno 中设置一个错误代码。
几点注意事项:
- 使用
mmap()创建的映射应当在不再需要时使用munmap()释放。 - 当映射文件时,文件的长度应该大于或等于要映射的长度。可以使用
ftruncate()调整文件大小。 - 写入映射区域超出文件当前大小的部分可能会导致段错误。
- 对于
MAP_SHARED映射,更改将写回底层文件,但不一定立即写回。可以使用msync()来确保更改被同步到文件。
总的来说,mmap() 是一种强大而灵活的机制,用于文件I/O和进程间通信。
munmap()
munmap() 是一个Unix和POSIX系统调用,用于取消映射一个之前通过 mmap() 映射到进程地址空间的内存区域。映射的内存区域可能是文件的映射、匿名内存或其他类型的内存对象。
当我们不再需要访问一个内存映射或当进程完成其操作并想释放资源时,应该调用 munmap() 来取消映射。
以下是 munmap() 的基本参数和它们的描述:
-
地址 (
addr):- 要取消映射的内存区域的起始地址。这应该是之前
mmap()调用的返回值。
- 要取消映射的内存区域的起始地址。这应该是之前
-
长度 (
length):- 要取消映射的内存区域的长度(以字节为单位)。
函数的基本原型如下:
int munmap(void *addr, size_t length);
返回值:
- 成功时,
munmap()返回0。 - 失败时,返回
-1,并设置全局变量errno以指示错误原因。
一些常见的使用场景和注意事项:
-
资源管理:
- 在不需要访问映射内存区域时,应及时使用
munmap()释放资源。否则,这可能会导致资源泄漏,尤其是在长时间运行的程序中。
- 在不需要访问映射内存区域时,应及时使用
-
访问已取消映射的内存:
- 一旦使用
munmap()取消映射了一个内存区域,任何尝试访问该区域的操作都将导致未定义的行为,通常是段错误 (segmentation fault)。
- 一旦使用
-
映射边界:
- 当取消映射一个内存区域时,必须确保
addr和length正确地对应于原始mmap()调用的值。尝试部分取消映射或使用不正确的地址和长度可能导致错误。
- 当取消映射一个内存区域时,必须确保
-
与其他资源的关联:
- 取消映射并不意味着与该映射相关的其他资源也被释放。例如,如果映射了一个文件,
munmap()只会取消映射,但不会关闭文件。我们仍然需要使用close()系统调用来关闭文件。
- 取消映射并不意味着与该映射相关的其他资源也被释放。例如,如果映射了一个文件,
总的来说,munmap() 是内存映射管理的重要部分,正确地使用它可以帮助避免资源泄漏和确保程序的稳定性。在设计使用内存映射的应用程序时,我们应该始终确保在不再需要映射的时候调用 munmap() 来释放资源。
ftruncate()
ftruncate() 是一个系统调用,用于调整/设置已打开的文件的大小。这个调用可以使文件变大或变小。当文件增大时,新增的部分会被视为“空洞”,并且会读取为零字节;当文件缩小时,超出指定长度的部分将被丢弃。
以下是 ftruncate() 的基本参数和它们的描述:
-
文件描述符 (
fd):- 这是要调整大小的文件的文件描述符。通常,这是使用
open()或其他相关系统调用获得的。
- 这是要调整大小的文件的文件描述符。通常,这是使用
-
长度 (
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”。
简而言之:
-
试图读取超出文件长度但在映射区域内的地址:通常会读到0,这是因为文件被视为以0字节填充直到映射的大小。
-
试图访问超出映射区域的地址:通常会导致段违规错误(segmentation fault)。
因此,最好确保只访问映射的内存区域内的地址,避免超出这个范围,以防止未定义的行为和潜在的程序崩溃。
相关文章:
Linux- 内存映射文件(Memory-Mapped File)
内存映射文件(Memory-Mapped File)是⼀种将文件内容映射到内存中的机制,允许程序直接访问文件数据,就好像这些数据已经被加载到了内存⼀样。这个机制允许文件的内容被映射到⼀个进程的地址空间,从而允许程序以⼀种更高…...
李航老师《统计学习方法》第五章阅读笔记
决策树(decision tree)是一种基本的分类与回归方法。本章主要讨论用于分类的决策树。决策树模型呈树形结构,在分类问题中,表示基于特征对实例进行分类的过程。 以下是关于分类决策树的一些基本概念和特点: 树形结构&am…...
iOS16新特性:实时活动-在锁屏界面实时更新APP消息 | 京东云技术团队
简介 之前在 《iOS16新特性:灵动岛适配开发与到家业务场景结合的探索实践》 里介绍了iOS16新的特性:实时更新(Live Activity)中灵动岛的适配流程,但其实除了灵动岛的展示样式,Live Activity还有一种非常实用的应用场景…...
使用 Elasticsearch、OpenAI 和 LangChain 进行语义搜索
在本教程中,我将引导您使用 Elasticsearch、OpenAI、LangChain 和 FastAPI 构建语义搜索服务。 LangChain 是这个领域的新酷孩子。 它是一个旨在帮助你与大型语言模型 (LLM) 交互的库。 LangChain 简化了与 LLMs 相关的许多日常任务,例如从文档中提取文本…...
NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061
今天发现,有两个处理器,启动以后,数据流不过去,后来,锁定问题在,queue队列上面,因为别的队列都可以通过,右键,empty queue清空,就是 这个队列不行,这个队列无法被删除,至于为什么导致这样的, 猜测是因为之前,流程设计好以后,队列没有设置背压,也没有设置队列中的内容大小和fl…...
leetcode20. 有效的括号 [简单题]
题目 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型…...
ubuntu20.04下源码编译colmap
由于稠密重建需要CUDA,因此先安装CUDA,我使用的是3050GPU,nvidia-smi显示最高支持CUDA11.4。 不要用sudo apt安装,版本较低,30系显卡建议安装CUDA11.0以上,这里安装了11.1版本。 下载: cuda_1…...
Jumpserver堡垒机
一、堡垒机概述 1、堡垒机的基本概念 堡垒机也是一台服务器,在一个特定的网络环境下,为了保障网络和数据不受来自外部和内部用户的入侵和破坏,而运用各种技术手段实时收集、监控网络环境中每一个组成部分(服务器)的系…...
第一百五十三回 如何实现滑动窗口
文章目录 概念介绍实现方法示例代码 我们在上一章回中介绍了自定义组件实现游戏摇杆相关的内容,本章回中将介绍 如何实现滑动窗口.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在本章回中介绍的滑动窗口表示在屏幕底部向上滑动时弹出一个窗口&a…...
Oracle 12c自动化管理特性的新进展:自动备份、自动恢复和自动维护功能的优势|oracle 12c相对oralce 11g的新特性(3)
一、前言: 前面几期讲解了oracle 12c多租户的使用、In-Memory列存储来提高查询性能以及数据库的克隆、全局数据字典和共享数据库资源的使用 今天我们讲讲oracle 12c的另外的一个自动化管理功能新特性:自动备份、自动恢复、自动维护的功能 二、自动备份、自动恢复、自动维护…...
Redis——Jedis中hash类型使用
hset 和 hget hset可以逐一添加key和value,也可以通过map类型来直接添加多组fields 而hget则返回string类型,如果元素不存在则返回null private static void hsetAndHget(Jedis jedis) {jedis.flushAll();jedis.hset("key", "f1"…...
肖sir__项目实战讲解__004
项目实战讲解 一、项目的类型 金融类: 保险(健康险理财险)、证券、基金(股票型基金、混合型基金、指数型基金、债券型基金、 天天基金网(ETF基金、货币型基金、量化基金)、银行、贷款、信用卡、外汇、二元期权、期货原油、blockchain、 数字货币、黄金白…...
数据库数据恢复-ORACLE常见故障有哪些?恢复数据的可能性高吗?
ORACLE数据库常见故障: 1、ORACLE数据库无法启动或无法正常工作。 2、ORACLE数据库ASM存储破坏。 3、ORACLE数据库数据文件丢失。 4、ORACLE数据库数据文件部分损坏。 5、ORACLE数据库DUMP文件损坏。 ORACLE数据库数据恢复可能性分析: 1、ORACLE数据库无…...
合规性管理如何帮助产品团队按时交付?
成功的产品和产品发布背后通常需要经过一个涉及多个监督机构、多功能团队和利益相关者的复杂流程。在组织的治理、风险管理和合规性(GRC)框架下,产品团队不仅需要追求市场创新,还需要确保符合所有适用的法规、标准和合同要求。由于…...
从平均数到排名算法
平均数用更少的数字,概括一组数字。属于概述统计量、集中趋势测度、位置测度。中位数是第二常见的概述统计量。许多情况下比均值更合适。算术平均数是3中毕达哥拉斯平均数之一,另外两种毕达哥拉斯平均数是几何平均数和调和平均数。 算术平均 A M 1 n ∑…...
如何使用ESP8266微控制器和Nextion显示器为Home Assistant展示温度传感器和互联网天气预报
第一部分:引言与项目概述 在智能家居领域,实时监控和显示环境数据已经成为了一个热门的话题。无论是室内温度、室外温度,还是游泳池的温度,都可以通过各种传感器轻松获取。但如何将这些数据以直观、美观的方式展现出来呢…...
阻塞队列-生产者消费者模型
阻塞队列介绍标准库阻塞队列使用基于阻塞队列的简单生产者消费者模型。实现一个简单型阻塞队列 (基于数组实现) 阻塞队列介绍 不要和之前学多线程的就绪队列搞混; 阻塞队列:也是一个队列,先进先出。带有特殊的功能 &…...
Vector Art - 矢量艺术
什么是矢量艺术? 矢量图形允许创意人员构建高质量的艺术作品,具有干净的线条和形状,可以缩放到任何大小。探索这种文件格式如何为各种规模的项目提供创造性的机会。 什么是矢量艺术作品? 矢量艺术是由矢量图形组成的艺术。这些图形是基于…...
ruoyi-nbcio增加flowable流程待办消息的提醒,并提供右上角的红字数字提醒(一)
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 1、数据库表方面 在原来sys_notice修改基础上增加一个表叫sys_notice_send 表结构如下: DROP …...
数据结构:二叉树的基本概念
文章目录 1. 二叉树的定义2. 二叉树的特点3. 特殊二叉树斜树满二叉树完全二叉树 4. 二叉树的性质 1. 二叉树的定义 如果我们猜一个100以内的数字,该怎么猜才能理论最快呢? 第一种方式:从1,2一直猜到100, 反正数字都是100以内,总能猜到的 第二种方式:先猜50,如果比结果小,猜75…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
