Linux使用mmap调用创建、读写和释放共享内存区域

 更新时间:2025年11月26日 09:02:31   作者:郝学胜-神的一滴  
共享内存是Linux系统中一种高效的进程间通信(IPC)机制,允许多个进程访问同一块物理内存区域,在所有IPC机制中,共享内存是最快的一种,因为它避免了数据在内核空间和用户空间之间的复制,本文将详细介绍如何使用mmap系统调用创建、读写和释放共享内存区域

1. 使用mmap创建映射区

mmap(memory map)是Linux系统提供的一个系统调用,用于将文件或设备映射到进程的地址空间。它也可以用于创建匿名映射区域,实现进程间的共享内存。

mmap函数原型

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

参数说明:

  • addr:指定映射区的起始地址,通常设为NULL,让系统自动选择合适的地址
  • length:映射区域的大小
  • prot:映射区域的保护标志,如PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行)等
  • flags:映射类型标志,如MAP_SHARED(共享)、MAP_PRIVATE(私有)等
  • fd:文件描述符,对于匿名映射设为-1
  • offset:文件映射的偏移量,通常设为0

使用mmap创建共享内存的步骤

  1. 打开或创建一个文件(对于文件映射)或使用匿名映射
  2. 调用mmap函数创建映射区
  3. 检查mmap的返回值,确保映射成功

示例代码:使用mmap创建匿名共享内存

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

int main() {
    // 定义映射区域大小
    size_t size = 4096;
    
    // 使用mmap创建匿名共享内存
    void *mapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    
    // 检查映射是否成功
    if (mapped == MAP_FAILED) {
        perror("mmap failed");
        return 1;
    }
    
    printf("Memory mapped at address %p\n", mapped);
    
    // 使用共享内存...
    
    // 释放映射区
    if (munmap(mapped, size) == -1) {
        perror("munmap failed");
        return 1;
    }
    
    return 0;
}

2. 读写映射区

一旦成功创建了映射区,进程就可以像操作普通内存一样读写该区域。需要注意的是,如果映射的是文件,对映射区的修改会反映到实际文件中(当使用MAP_SHARED标志时)。

读写映射区的注意事项

  1. 对于文件映射,修改的内容会在适当的时机写回文件(取决于系统实现)
  2. 多个进程同时访问共享内存时需要同步机制,如信号量、互斥锁等
  3. 不要越界访问映射区域,可能导致段错误

示例代码:读写映射区

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

int main() {
    // 定义映射区域大小
    size_t size = 4096;
    
    // 使用mmap创建匿名共享内存
    void *mapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    
    // 检查映射是否成功
    if (mapped == MAP_FAILED) {
        perror("mmap failed");
        return 1;
    }
    
    // 写入数据到映射区
    char *message = "Hello, shared memory!";
    strncpy((char *)mapped, message, strlen(message));
    
    // 读取并打印映射区内容
    printf("Read from shared memory: %s\n", (char *)mapped);
    
    // 释放映射区
    if (munmap(mapped, size) == -1) {
        perror("munmap failed");
        return 1;
    }
    
    return 0;
}

3. 使用munmap释放映射区

当进程不再需要使用映射区时,应该调用munmap函数释放该区域,释放的内存可以被系统重新分配。

munmap函数原型

#include <sys/mman.h>
int munmap(void *addr, size_t length);

参数说明:

  • addr:要释放的映射区的起始地址,必须是mmap返回的地址
  • length:要释放的区域大小,必须与mmap调用时的length参数相同

使用munmap的注意事项

  1. 确保传入正确的地址和大小
  2. 不要重复释放同一个映射区
  3. 释放映射区后,不应该再访问该区域的内存

示例代码:使用munmap释放映射区

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

int main() {
    // 定义映射区域大小
    size_t size = 4096;
    
    // 使用mmap创建匿名共享内存
    void *mapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    
    // 检查映射是否成功
    if (mapped == MAP_FAILED) {
        perror("mmap failed");
        return 1;
    }
    
    // 使用共享内存...
    
    // 释放映射区
    if (munmap(mapped, size) == -1) {
        perror("munmap failed");
        return 1;
    }
    
    printf("Memory unmapped successfully\n");
    return 0;
}

4. mmap的优缺点

优点

  1. 高效:共享内存是最快的IPC机制,因为数据不需要在内核和用户空间之间复制
  2. 灵活:可以映射文件或创建匿名共享内存
  3. 可以与文件系统结合使用,实现数据持久化

缺点

  1. 需要额外的同步机制:多个进程同时访问共享内存时需要同步
  2. 管理复杂:需要手动管理映射区的创建和释放
  3. 安全性较低:共享内存对所有具有访问权限的进程可见

5. 实际应用场景

  1. 大数据处理:多个进程共享处理大数据集
  2. 实时系统:需要低延迟数据交换的系统
  3. 数据库系统:多个进程共享数据缓存
  4. 图形处理:多个进程共享图像数据

6. 总结

mmap是Linux中实现共享内存的重要工具,它提供了一种高效的方式让多个进程共享内存区域。通过合理使用mmap、munmap以及适当的同步机制,可以实现高效的进程间通信。在实际应用中,需要根据具体需求选择合适的IPC机制,并在性能、安全性和复杂性之间做出权衡。

以上就是Linux使用mmap调用创建、读写和释放共享内存区域的详细内容,更多关于Linux mmap操作共享内存区域的资料请关注脚本之家其它相关文章!

相关文章

  • 学习在kernel态下使用NEON对算法进行加速的方法

    学习在kernel态下使用NEON对算法进行加速的方法

    这篇文章主要介绍了学习在kernel态下使用NEON对算法进行加速的方法,一起来学习下,大大提高数据运算的效率。
    2017-11-11
  • Linux如何分配home的磁盘空间给根目录

    Linux如何分配home的磁盘空间给根目录

    这篇文章主要介绍了Linux如何分配home的磁盘空间给根目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2026-03-03
  • Linux date 时间设置同步命令分享

    Linux date 时间设置同步命令分享

    Linux服务器运行久时,系统时间就会存在一定的误差,一般情况下可以使用date命令进行时间设置,但在做数据库集群分片等复杂操作时对多台机器的时间差是有要求的,此时就需要使用ntpdate进行时间同步。
    2018-04-04
  • 深入理解Linux负载均衡LVS

    深入理解Linux负载均衡LVS

    LVS是Linux Virtual Server 的简称,也就是linux虚拟服务器。LVS 是一个实现负载均衡集群的开源软件项目,LVS架构从逻辑上可分为调度层、Server集群层和共享存储
    2021-06-06
  • 使用fcntl系统函数在Linux下改变文件属性的操作指南

    使用fcntl系统函数在Linux下改变文件属性的操作指南

    在 Linux 系统编程中,fcntl 是一个非常强大且灵活的系统调用,允许开发者对文件描述符进行各种操作,包括设置和获取文件属性、管理文件锁等,本文将深入探讨 fcntl 的功能及其在实际开发中的应用,需要的朋友可以参考下
    2025-10-10
  • CentOS 7 安装 MySQL 5.6遇到的各种问题小结

    CentOS 7 安装 MySQL 5.6遇到的各种问题小结

    在一测试服务器(CentOS Linux release 7.2.1511)上安装MySQL 5.6(5.6.19 MySQL Community Server)时遇到了很多奇葩问题,今天小编给大家总结了关于entOS 7 安装 MySQL 5.6遇到的各种问题,需要的朋友一起看看吧
    2016-11-11
  • Linux使用publick key登录过程(无密码登录)

    Linux使用publick key登录过程(无密码登录)

    这篇文章主要介绍了Linux使用publick key登录过程(无密码登录),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2026-03-03
  • Linux服务器如何修改默认的远程连接端口

    Linux服务器如何修改默认的远程连接端口

    这篇文章主要介绍了Linux服务器如何修改默认的远程连接端口问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Linux进程使用文件进行通信的常用方法

    Linux进程使用文件进行通信的常用方法

    在Linux系统中,进程间通信(IPC)是构建复杂应用的关键技术,使用文件进行通信是一种简单而有效的方法,特别适合需要持久化数据或跨系统边界的场景,本文将介绍几种主要的文件通信技术及其应用场景,需要的朋友可以参考下
    2025-11-11
  • Linux服务器快速搭建MinIO对象存储全过程

    Linux服务器快速搭建MinIO对象存储全过程

    在Linux服务器上搭建MinIO存储服务器的步骤,MinIO支持从二进制文件或包管理器下载,用户需要配置环境变量、创建存储目录并设置服务权限,然后启动服务并访问Web控制台进行验证,文章还提到可配置防火墙、Nginx反向代理及多节点部署
    2025-09-09

最新评论