mmap概念

mmp是 将文件或设备直接映射到进程的虚拟内存空间 的一种机制,可实现程序像访问内存一样访问文件,而不需要传统的 read()/write()系统调用

文件内容被映射到进程的地址空间,读写文件就像操作内存一样,操作系统负责自动同步内存和文件的修改(除非显式禁用)。
好处:

  • 文件 I/O 优化:避免频繁的 read()/write(),提升性能,例如数据库引擎(如 SQLite、LevelDB)用 mmap加速磁盘访问
  • 多个进程需要高效共享数据(如父子进程、独立进程),比管道、消息队列更快(直接内存访问),Chrome 浏览器用 mmap共享多个标签页的内存,机器学习训练时,多个进程共享模型参数
  • 序运行时加载动态链接库(.so/.dll)时,库文件被映射到内存,按需加载(懒加载),节省内存
  • sendfile:文件通过 mmap映射到内存,直接通过 DMA 发送到网卡,无需 CPU 参与拷贝

语法:函数声明

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数说明
addr建议映射的起始地址(通常传 NULL,由系统自动分配)
length映射区域的长度(字节)
prot内存保护方式(PROT_READ, PROT_WRITE 等)
flags映射类型(MAP_SHARED, MAP_PRIVATE
fd文件描述符(通过 open 获得)
offset文件映射起始偏移(必须是页大小的整数倍)

相关常量:

// 保护方式
PROT_READ      // 可读
PROT_WRITE     // 可写
PROT_EXEC      // 可执行
PROT_NONE      // 不可访问// 映射类型
MAP_SHARED     // 修改会写回文件,进程间共享
MAP_PRIVATE    // 写时复制,修改不写回文件// 取消映射
int munmap(void *addr, size_t length);  // 释放映射

mmap写文件

[root@prs31 01-fd]# cat 01-mmap_read.c 
// 01-mmap_read.c#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>int main() {int fd;struct stat sb;char *mapped;fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("open");exit(1);}// 2. 获取文件状态(主要是大小)if (fstat(fd, &sb) == -1) {perror("fstat");exit(1);}// 3. 映射文件到内存mapped = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);if (mapped == MAP_FAILED) {perror("mmap");close(fd);exit(1);}// 4. 像访问数组一样读取内容printf("文件内容:\n");for (off_t i = 0; i < sb.st_size; i++) {putchar(mapped[i]);     // 逐字符打印内存映射文件(mmap)的内容}// 5. 解除映射if (munmap(mapped, sb.st_size) == -1) {perror("munmap");}close(fd);return 0;
}

在这里插入图片描述

mmap追加文件内容

[root@prs31 01-fd]# cat 02-mmap_write.c 
// mmap_write.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>int main() {int fd;struct stat sb;char *mapped;const char *new_content = "\nAppended via mmap!";// 1. 以读写方式打开文件fd = open("test.txt", O_RDWR);if (fd == -1) {perror("open");exit(1);}// 2. 获取文件大小if (fstat(fd, &sb) == -1) {perror("fstat");exit(1);}// 3. 扩展文件大小(为追加内容预留空间)off_t new_size = sb.st_size + strlen(new_content);if (ftruncate(fd, new_size) == -1) {perror("ftruncate");close(fd);exit(1);}// 4. 映射整个新大小的文件,这里传递使用扩展后的文件大小mapped = mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (mapped == MAP_FAILED) {perror("mmap");close(fd);exit(1);}// 5. 在原内容末尾写入新内容,strcpy(目的变量,要添加的变量)strcpy(mapped + sb.st_size, new_content);printf("已追加内容到文件\n");if (munmap(mapped, new_size) == -1) {perror("munmap");}close(fd);return 0;
}

在这里插入图片描述

mmap实现进程间共享内存

[root@prs31 01-fd]# cat 03-shm_writer.c 
// 03-shm_writer.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>int main() {int fd;char *mapped;// 1. 创建共享文件fd = open("/tmp/shm_file", O_CREAT | O_RDWR, 0644);if (fd == -1) {perror("open");exit(1);}// 2. 扩展文件大小ftruncate(fd, 4096);  // 1页// 3. 映射mapped = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (mapped == MAP_FAILED) {perror("mmap");exit(1);}// 4. 写入数据sprintf(mapped, "Hello from Process A (PID: %d)", getpid());printf("写入: %s\n", mapped);printf("等待按回车继续...\n");getchar();  // 等待进程B读取munmap(mapped, 4096);close(fd);return 0;
}

[root@prs31 01-fd]# cat 03-shm_reader.c 
// 03-shm_writer
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>int main() {int fd;char *mapped;fd = open("/tmp/shm_file", O_RDONLY);if (fd == -1) {perror("open");exit(1);}mapped = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);if (mapped == MAP_FAILED) {perror("mmap");exit(1);}printf("读取到: %s\n", mapped);munmap(mapped, 4096);close(fd);return 0;
}

运行代码

[root@prs31 01-fd]# gcc 03-shm_writer.c shm_writer
[root@prs31 01-fd]# gcc 03-shm_reader.c shm_reader

在这里插入图片描述

第二个终端:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92854.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92854.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/92854.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CPP继承

继承 一、继承概述 1、为什么需要继承 如下示例&#xff0c;Person 类、Student 类、Teacher 类有大量重复的代码&#xff0c;造成代码冗余&#xff0c;降低开发效率。我们可以通过继承来解决这一问题。在面向对象的编程语言中&#xff0c;继承是一个核心概念。主要作用将重复的…

模块 PCB 技术在未来通信领域的创新突破方向

未来通信领域对数据传输速率、信号稳定性及设备集成度的要求持续攀升&#xff0c;模块 PCB 作为通信设备的关键组件&#xff0c;其技术创新成为推动行业发展的核心动力。猎板 PCB 凭借深厚的技术积累与持续的研发投入&#xff0c;在模块 PCB 技术创新方面取得诸多突破&#xff…

mysql的InnoDB索引总结

MySQL InnoDB索引知识点总结 1. 索引类型 1.1 聚簇索引&#xff08;Clustered Index&#xff09; 定义与特性 定义&#xff1a;聚簇索引是InnoDB的默认存储方式&#xff0c;数据行按照主键的顺序物理存储在磁盘上特性&#xff1a; 每个InnoDB表只能有一个聚簇索引数据页中的记录…

C++模板的补充

类模板(上一篇没讲到类模板C/C内存管理&函数模板-CSDN博客&#xff09; 类模板的定义&#xff1a; template<class T1, class T2, ..., class Tn> class 类模板名 {// 类内成员定义 }; 用一个简单的栈例子讲类模板 #define _CRT_SECURE_NO_WARNINGS #include &l…

用JOIN替代子查询的查询性能优化

一、子查询的性能瓶颈分析‌重复执行成本‌关联子查询会导致外层每行数据触发一次子查询&#xff0c;时间复杂度为O(M*N)sql-- 典型低效案例 SELECT e.employee_id, (SELECT d.department_name FROM departments d WHERE d.department_id e.department_id) FROM employees e; …

【设计模式】访问者模式模式

访问者模式&#xff08;Visitor Pattern&#xff09;详解一、访问者模式简介 访问者模式&#xff08;Visitor Pattern&#xff09; 是一种 行为型设计模式&#xff08;对象行为型模式&#xff09;&#xff0c;它允许你在不修改对象结构的前提下&#xff0c;为对象结构中的元素添…

比特币现货和比特币合约的区别与联系

一、基本定义项目现货&#xff08;Spot&#xff09;合约&#xff08;Futures / Perpetual&#xff09;本质直接买卖比特币本身买卖比特币价格的衍生品合约所得资产真实的 BTC合约头寸&#xff08;没有直接持有 BTC&#xff09;结算方式交割比特币现金结算&#xff08;多数平台&…

Qt/C++开发监控GB28181系统/实时监测设备在线离线/视频预览自动重连/重新点播取流/低延迟

一、前言说明 一个好的视频监控系统&#xff0c;设备掉线后能够自动重连&#xff0c;也是一个重要的功能指标&#xff0c;如果监控系统只是个rtsp流地址&#xff0c;那非常好办&#xff0c;只需要重新打开流地址即可&#xff0c;而gb28181中就变得复杂了很多&#xff0c;需要多…

此芯p1开发板使用OpenHarmony时llama.cpp不同优化速度对比(GPU vs CPU)

硬件环境 Cix P1 SoC 瑞莎星睿 O6 开发板 rx580显卡 产品介绍&#xff1a; https://docs.radxa.com/orion/o6/getting-started/introduction OpenHarmony 5.0.0 使用vulkan后端的llama.cpp &#xff08;GPU&#xff09; # ./llama-bench -m /data/qwen1_5-0_5b-chat-q2_k.…

Android 四大布局:使用方式与性能优化原理

一、四大布局基本用法与特点1. LinearLayout&#xff08;线性布局&#xff09;使用方式&#xff1a;<LinearLayoutandroid:orientation"vertical" <!-- 排列方向&#xff1a;vertical/horizontal -->android:layout_width"match_parent"android:…

Redis的BigKey问题

Redis的BigKey问题 什么是大Key问题&#xff1f; 大key问题其实可以说是大value问题&#xff0c;就是某个key对应的value所占据的存储空间太大了&#xff0c;所以导致我们在操作这个key的时候花费的时间过长&#xff08;序列化\反序列化&#xff09;&#xff0c;从而降低了redi…

TDengine IDMP 产品基本概念

基本概念 元素 (Element) IDMP 通过树状层次结构来组织数据&#xff0c;树状结构里的每个节点被称之为元素 (Element)。元素是一个物理的或逻辑的实体。它可以是具体的物理设备&#xff08;比如一台汽车&#xff09;&#xff0c;物理设备的一个子系统&#xff08;比如一台汽车的…

专题二_滑动窗口_将x减到0的最小操作数

一&#xff1a;题目解释&#xff1a;每次只能移除数组的边界&#xff0c;移除的边界的总和为x&#xff0c;要求返回你移除边界的最小操作数&#xff01;也就是说你最少花几次移除边界&#xff0c;就能够让这些移除的边界的和为x&#xff0c;则返回这个次数&#xff01;所以这个…

CentOS 7 下通过 Anaconda3 运行llm大模型、deepseek大模型的完整指南

CentOS 7 下通过 Anaconda3 运行llm大模型、deepseek大模型的完整指南A1 CentOS 7 下通过 Anaconda3 运行大模型的完整指南一、环境准备二、创建专用环境三、模型部署与运行四、优化配置常见问题解决B1 CentOS 7 下通过 Anaconda3 使用 CPU 运行 DeepSeek 大模型的完整方案一、…

Flutter应用在Windows 8上正常运行

要让Flutter应用在Windows 8上正常运行,需满足以下前提条件,涵盖系统环境、依赖配置、编译设置等关键环节: 一、系统环境基础要求 Windows 8版本 必须是 Windows 8.1(核心支持),不支持早期Windows 8(需升级到8.1,微软已停止对原版Windows 8的支持)。 确认系统版本:右…

Redis实现消息队列三种方式

参考 Redis队列详解&#xff08;springboot实战&#xff09;_redis 队列-CSDN博客 前言 MQ消息队列有很多种&#xff0c;比如RabbitMQ,RocketMQ,Kafka等&#xff0c;但是也可以基于redis来实现&#xff0c;可以降低系统的维护成本和实现复杂度&#xff0c;本篇介绍redis中实现…

【C++动态版本号生成方案:实现类似C# 1.0.* 的自动构建号】

C动态版本号生成方案&#xff1a;实现类似C# 1.0.* 的自动构建号 在C#中&#xff0c;1.0.*版本号格式会在编译时自动生成构建号和修订号。本文将介绍如何在C项目中实现类似功能&#xff0c;通过MSBuild自动化生成基于编译时间的版本号。 实现原理 版本号构成&#xff1a;主版本…

【算法题】:斐波那契数列

用 JavaScript 实现一个 fibonacci 函数&#xff0c;满足&#xff1a; 输入 n&#xff08;从0开始计数&#xff09;输出第 n 个斐波那契数&#xff08;斐波那契数列从 1 开始&#xff1a;1,1,2,3,5,8,13,21…&#xff09; 示例&#xff1a; fibonacci(0) > 1fibonacci(4) &g…

【YOLOv13[基础]】热力图可视化实践 | 脚本升级 | 优化可视化效果 | 论文必备 | GradCAMPlusPlus, GradCAM, XGradCAM, EigenCAM等

本文将进行添加YOLOv13版本的升级版热力图可视化功能的实践,支持图像热力图可视化、优化可视化效果、 可以选择使用GradCAMPlusPlus, GradCAM, XGradCAM, EigenCAM, HiResCAM, LayerCAM, RandomCAM, EigenGradCAM。一个参数即可设置是否显示检测框等。 原图 结果图

ElasticSearch相关术语介绍

1.RESTful风格程序REST(英文全称为:"Representational State Transfer")指的是一组架构约束条件和原则。它是一种软件架构风格&#xff08;约束条件和原则的集合&#xff0c;但并不是标准&#xff09;。 REST通过资源的角度观察网络&#xff0c;以URI对网络资源进行…