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

Linux系统编程之内存映射

概述

        内存映射是操作系统提供的一种机制,使得文件或设备的内容可以直接映射到进程的虚拟地址空间中。这意味着,我们可以像访问数组一样读写文件内容,而不需要显式地调用I/O函数进行数据传输。内存映射适用于多种应用场景,包括但不限于:大文件处理、数据库和缓存、进程间通信、内存映射文件等。

        内存映射的优势主要体现在如下三个方面。

        1、提高性能:减少了从磁盘到用户空间的数据复制过程。

        2、简化编程模型:可以通过指针直接访问文件内容,就像操作普通内存一样。

        3、支持共享内存:多个进程可以共享同一块内存映射区域,实现高效的进程间通信。

mmap和munmap

        mmap函数用于创建一个新的内存映射或扩展现有的映射,以将文件或设备映射到内存中。通过mmap,我们可以直接访问文件内容,就像操作内存一样简单和高效。这种机制特别适用于需要处理大文件、实现进程间通信、或需要频繁读写特定文件部分的应用场景。其函数原型如下。

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

        各个参数和返回值的含义如下。

        addr:建议的映射起始地址,通常设置为NULL,让操作系统自动选择合适的地址。

        length:映射区域的长度,以字节为单位。

        prot:内存保护标志,指定映射区域的访问权限,取值如下。

        (1)PROT_READ:映射区域可以被读取。

        (2)PROT_WRITE:映射区域可以被写入。

        (3)PROT_EXEC:映射区域可以被执行。

        (4)PROT_NONE:映射区域不可访问。

        flags:指定映射类型的标志,取值如下。

        (1)MAP_SHARED:变更会被共享给其他进程,并且会同步更新到文件中。

        (2)MAP_PRIVATE:创建一个私有副本,变更仅对当前进程可见,不会同步回文件。

        (3)MAP_ANONYMOUS:映射匿名内存,不关联任何文件描述符。

        fd:文件描述符。如果使用了MAP_ANONYMOUS标志,则此参数应设为-1。

        offset:文件中的偏移量,指定了映射区域在文件中的起始位置。

        返回值:成功时返回指向映射区域的指针,失败时返回MAP_FAILED,并设置errno为具体的错误原因。

        munmap函数用于解除之前通过mmap建立的内存映射。它会将指定的地址范围从调用进程的地址空间中删除,并释放相应的资源。其函数原型如下。

int munmap(void *addr, size_t length);

        各个参数和返回值的含义如下。

        addr:要解除映射的内存区域的起始地址。

        length:内存区域的长度。

        返回值:成功时返回0,失败时返回-1,并设置errno为具体的错误原因。

实战代码

        下面的实战代码使用内存映射技术来读取并打印一个文件的内容。

        首先,我们通过调用open函数以只读模式打开名为"hope_wisdom.txt"的文件。接着,使用fstat函数获取文件的统计信息,包括文件大小。然后,通过mmap函数将整个文件内容映射到进程的地址空间中,映射区域设置为只读且私有。这就意味着,对映射内容的任何修改都不会反映到原文件上。

        成功映射后,我们直接将映射区域的内容作为字符串打印出来。最后,通过munmap函数解除了文件内容的内存映射,并关闭了文件描述符。

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>int main()
{int fd = open("hope_wisdom.txt", O_RDONLY);if (fd == -1){printf("open failed\n");return 1;}// 获取文件大小struct stat sb;if (fstat(fd, &sb) == -1){printf("fstat failed\n");close(fd);return 1;}// 映射文件off_t length = sb.st_size;void *pAddr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);if (pAddr == MAP_FAILED){printf("mmap failed\n");close(fd);return 1;}// 打印内容printf("%s", (char *)pAddr);// 解除映射munmap(pAddr, length);close(fd);return 0;
}

http://www.xdnf.cn/news/2250.html

相关文章:

  • 深入浅出理解并应用自然语言处理(NLP)中的 Transformer 模型
  • 【Pandas】pandas DataFrame rdiv
  • 第6讲:科学配色基础——认识颜色空间(RGB、HSV、HCL)
  • AI图像编辑器 Luminar Neo 便携版 Win1.24.0.14794
  • Tableau 基础表制作
  • Java在云计算、大数据、云原生下的应用和优势 - 面试实战
  • 使用 OpenCV 进行视觉图片调整的几种常见方法
  • 碰一碰发视频源码搭建全解析,支持OEM
  • Ubuntu下安装vsode+qt搭建开发框架(二)
  • STM32 开发 - stm32f10x.h 头文件(内存映射、寄存器结构体与宏、寄存器位定义、实现点灯案例)
  • i18n-ai-translate开源程序,可以使用DeepSeek等模型将您的 i18nJSON翻译成任何语言
  • stm32之EXIT外部中断详解
  • (done) 吴恩达版提示词工程 5. 推理 (情绪分类,控制输出格式,输出 JSON,集成多个任务,文本主题推断和索引,主题内容提醒)
  • 基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
  • JAVA服务内存缓慢上涨,年轻代GC正常但Full GC频繁,如何定位?
  • IntelliJ IDEA修改实体类成员变量的名称(引入了该实体类的全部文件也会自动更新变量的名称)
  • 精益数据分析(25/126):关键指标驱动业务发展
  • GPT系列模型-20250426
  • Spring Boot 3.4 实战指南:从性能优化到云原生增强
  • 嵌入式C设计模式---策略模式
  • 跨境支付接口RT从300ms突增至2000ms,但CPU/Memory无异常,如何排查?
  • 测试模板x
  • 浏览器界面无显示,提示“代理服务器可能有问题”,这是怎么回事呢?
  • 在 Vue 3 setup() 函数中使用 TypeScript 处理 null 和 undefined 的最佳实践
  • Redis的两种持久化方式:RDB和AOF
  • WPF核心技术解析与使用示例
  • 【Redis】基础2:作为缓存
  • 力扣刷题Day 31:删除链表的倒数第N个结点(19)
  • Linux之netlink(2)libnl使用介绍(1)
  • 6.2 内容生成与营销:个性化内容创作与营销策略优化