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

mmap函数的概念和使用方案

mmap 是 Linux 中用于内存映射的系统调用,允许将文件或设备直接映射到进程的地址空间,从而实现高效的文件访问或进程间通信。以下是对其概念和使用方案的详细说明:


1. 核心概念

  • 内存映射:将文件内容直接关联到进程的虚拟内存空间,使得文件操作如同内存读写,避免频繁的 read/write 系统调用。
  • 优势:减少数据拷贝、支持随机访问、便于共享内存。
  • 场景:大文件处理、进程间通信、高效I/O操作。

2. 函数原型

#include <sys/mman.h>

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

3. 参数详解

  • addr: 建议的映射起始地址,通常设为 NULL(由内核选择)。
  • length: 映射区域的长度。
  • prot: 内存保护模式(按位或组合):
    • PROT_READ(可读)
    • PROT_WRITE(可写)
    • PROT_EXEC(可执行)
    • PROT_NONE(不可访问)
  • flags: 映射类型和属性(常用值):
    • MAP_SHARED:修改同步到文件,多进程共享。
    • MAP_PRIVATE:写时复制,修改不写入文件。
    • MAP_ANONYMOUS:匿名映射(不依赖文件,用于进程间共享内存)。
  • fd: 文件描述符(匿名映射时设为 -1)。
  • offset: 文件中的偏移量(通常为 0)。

4. 使用步骤

  1. 打开文件:获取文件描述符 fd
  2. 获取文件信息:如通过 fstat 获取文件大小。
  3. 调用 mmap:创建内存映射,获得指向映射区域的指针。
  4. 操作内存:通过指针读写数据(如操作数组)。
  5. 解除映射:使用 munmap 释放内存。
  6. 关闭文件:关闭文件描述符。

5. 示例代码

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    // 1. 打开文件
    int fd = open("example.txt", O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // 2. 调整文件大小(确保足够大)
    ftruncate(fd, 4096);  // 扩展为 4KB

    // 3. 创建内存映射
    void *addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        close(fd);
        exit(EXIT_FAILURE);
    }

    // 4. 操作映射内存
    sprintf((char *)addr, "Hello from mmap!");
    printf("File content: %s\n", (char *)addr);

    // 5. 解除映射并清理
    if (munmap(addr, 4096) == -1) {
        perror("munmap");
    }
    close(fd);

    return 0;
}

6. 注意事项

  • 文件大小与映射长度:若映射长度超出文件大小,访问超出部分会触发 SIGBUS。需提前用 ftruncate 调整文件大小。
  • 权限匹配prot 参数需与文件打开模式兼容(如只读文件不可写)。
  • 同步数据MAP_SHARED 修改会由内核异步写回文件,立即同步需调用 msync
  • 错误处理:检查 mmap 返回值是否为 MAP_FAILED,处理 errno
  • 信号处理:非法访问可能触发 SIGSEGV(段错误)或 SIGBUS(总线错误)。
  • 匿名映射:使用 MAP_ANONYMOUSfd = -1 创建进程间共享内存。

7. 常见用途

  • 高效文件I/O:处理大文件时减少拷贝开销。
  • 进程间通信 (IPC):共享内存通过 MAP_SHARED 映射同一文件。
  • 内存分配:替代 malloc 进行大块内存分配(如 glibcmalloc 实现)。

正确使用 mmap 可显著提升性能,但需谨慎处理边界条件和错误,确保程序健壮性。

http://www.dtcms.com/a/113228.html

相关文章:

  • 爬楼梯问题-动态规划
  • 3536 矩形总面积
  • leetcode4.寻找两个正序数组中的中位数
  • 类 和 对象 的介绍
  • 2024 .11-2025.3 一些新感悟
  • 【33期获取股票数据API接口】如何用Python、Java等五种主流语言实例演示获取股票行情api接口之沪深A股当天逐笔交易数据及接口API说明文档
  • 【2020】【论文笔记】相变材料与超表面——
  • 使用Cusor 生成 Figma UI 设计稿
  • 数据库并发控制问题
  • 麒麟系统桌面版本v10安装教程
  • 【动手学深度学习】卷积神经网络(CNN)入门
  • 低代码开发平台:飞帆画 echarts 柱状图
  • pygame里live2d的使用方法(live2d-py)
  • 人工智能与计算机技术赋能高中教育数字化教学模式的构建与实践
  • Git 分布式版本控制工具
  • 【ROS2】〇、ROS2的安装
  • 神经网络与深度学习:案例与实践——第三章(2)
  • 3D图像重建中Bundle Adjustment的推导与实现
  • Shell脚本笔记
  • Java第三节:新手如何用idea创建java项目
  • #SVA语法滴水穿石# (004)关于 ended 和 triggered 用法
  • Java HttpURLConnection修仙指南:从萌新到HTTP请求大能的渡劫手册
  • #SVA语法滴水穿石# (005)关于 问号表达式(condition ? expr1 : expr2)
  • Arduino示例代码讲解:ADXL3xx 加速传感器
  • Java 类型转换和泛型原理(JVM 层面)
  • 论定制开发开源 AI 智能名片 S2B2C 商城小程序源码在零售变革中的角色与价值
  • 基于sklearn实现文本摘要思考
  • Linux进程间通信——有名管道
  • 【AI论文】基础智能体(Foundation Agents)领域的进展与挑战:从类脑智能到进化型、协作型及安全型系统
  • 数据化管理(二)---寻找零售密码