Linux系统调用之mmap,munmap函数

news/2024/10/30 13:31:21/

前言

如果,想要深入的学习Linux系统调用中的mmap,munmap函数,还是需要去自己阅读Linux系统中的帮助文档。

具体输入命令:

man 2 mmap/munmap

即可查阅到完整的资料信息。

mmap函数

在Linux中,mmap()是一个用于创建内存映射的系统调用函数。它可以将文件、设备或匿名内存映射到进程的虚拟地址空间。通过内存映射,进程可以直接通过虚拟地址访问映射区域的内容,从而提高文件访问效率,简化数据共享等。

mmap()函数的原型如下:

#include <sys/mman.h> //使用这个函数需导入此头文件
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

参数说明:

  • void *addr: 指定映射区域的起始地址。通常设为NULL,让操作系统自动选择合适的地址。
  • size_t length: 映射区域的大小,以字节为单位。
  • int prot: 映射区域的访问权限。可选值有:
    • PROT_NONE: 不允许访问。
    • PROT_READ: 允许读取。
    • PROT_WRITE: 允许写入。
    • PROT_EXEC: 允许执行。
    • 这些值可以通过按位或(|)运算符组合使用。
  • int flags: 指定映射的类型和其他属性。主要选项有:
    • MAP_SHARED: 创建一个共享映射。对映射区域的修改将写回到文件或共享内存中。
    • MAP_PRIVATE: 创建一个私有映射。对映射区域的修改不会影响其他进程或文件。
    • MAP_FIXED: 使用指定的地址进行映射。不建议使用,因为可能导致现有映射被覆盖。
    • MAP_ANONYMOUS: 创建一个匿名映射。此时,fd参数会被忽略,映射区域不关联任何文件。
    • 使用的方法类似于prot,这些值可以通过按位或(|)运算符组合使用
  • int fd: 文件描述符,指定要映射的文件。对于匿名映射,该参数需设置成-1
  • off_t offset: 文件中的偏移量,表示映射区域的起始位置。通常要求是系统内存页大小的整数倍。

mmap()函数返回值:

  • 成功时返回映射区域的起始地址;
  • 失败时返回MAP_FAILED(通常是(void *)-1)

创建内存映射后,可以使用指针操作映射区域,就像操作普通内存一样。需要注意的是,对映射区域的修改可能会导致文件或共享内存的内容发生变化,具体取决于映射类型(MAP_SHARED或MAP_PRIVATE)。

munmap函数

当我们使用内存映射完毕后,应调用munmap()函数解除内存映射,释放相关资源。

munmap()函数的原型如下:

#include <sys/mman.h> //使用这个函数需导入此头文件
int munmap(void *addr, size_t length);

参数说明:

  • void *addr: 映射区域的起始地址,即mmap()函数的返回值。
  • size_t length: 映射区域的大小,以字节为单位。应与mmap()函数中的length参数相同。

munmap()函数返回值

  • 成功时返回0;
  • 失败时返回-1。

使用匿名映射(内存映射的一种)进行父子进程间通信

下面是一个简单的示例,演示如何使用内存映射技术,利用mmap()和munmap()函数,达到父子间进程间通信的目的。子进程往共享内存中去写数据,父进程去读取子进程写入的数据。

/*
使用内存映射技术,达到父子间进程间通信的目的。子进程往共享内存中去写数据,父进程去读取子进程写入的数据。
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>int main()
{// 打开文件映射(这里使用的是匿名映射,内存映射的一种)void *ptr = mmap(NULL, 64, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);if (ptr == MAP_FAILED){perror("mmap");return -1;}// 创建子进程int pid = fork();if (pid > 0){wait(NULL); // 等待子进程结束,再从内存映射区读取文件printf("来自子进程的信息:%s\n", (char *)ptr);}else if (pid == 0){strcpy((char *)ptr, "hello,world");}else{perror("fork");munmap(ptr, 64);return -1;}//关闭内存映射munmap(ptr, 64);return 0;
}

使用mmap函数的易错点

在使用 Linux 的 mmap 函数时,有一些常见的易错点需要注意。下面是一些关键的易错点:

  1. 权限设置错误:在调用 mmap 函数时,需要提供适当的权限。例如,如果要求读写内存,则权限应为 PROT_READ | PROT_WRITE。如果权限设置错误,可能导致访问内存时出现问题。

  2. 文件描述符错误:如果是将文件映射到内存,需要提供正确的文件描述符。如果文件描述符错误,可能导致映射失败。

  3. 错误的文件偏移量:mmap 函数要求文件偏移量为页面大小的整数倍。如果提供了错误的偏移量,函数可能会失败。

  4. 映射长度错误:映射长度应大于零,否则 mmap 会失败。确保提供正确的映射长度。

  5. 映射地址错误:虽然在大多数情况下可以将映射地址设置为 NULL,以便系统选择合适的地址,但在某些情况下,可能需要指定映射地址。确保提供正确的映射地址,否则可能导致错误。

  6. 错误的标志:确保使用正确的标志(例如,MAP_SHARED 或 MAP_PRIVATE)。错误的标志可能导致映射失败或其他问题。

  7. 检查 mmap 返回值:mmap 函数在出错时返回 MAP_FAILED((void *)-1),确保在使用返回的指针之前检查是否为 MAP_FAILED。

  8. 忘记使用 munmap:使用完映射后,不要忘记调用 munmap 函数来解除映射。否则,可能导致资源泄漏。

  9. 多线程同步:如果在多线程环境中使用 mmap,确保在访问映射内存时进行适当的同步。否则,可能导致竞争条件和不一致的数据。

  10. 对匿名映射使用 MAP_FIXED:当需要匿名映射时,避免使用 MAP_FIXED 标志,因为这可能导致覆盖现有映射。通常可以使用 MAP_FIXED_NOREPLACE,以便在指定地址已被使用时,映射失败而不会覆盖现有映射。

注意这些易错点有助于在使用 mmap 函数时避免常见错误,从而提高代码的可靠性和稳定性。


http://www.ppmy.cn/news/43939.html

相关文章

Python 字符串format()格式化 / 索引

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 为了确保字符串按预期显示&#xff0c;我们可以使用 format() 方法对结果进行格式化。 字符串 format() format() 方法允许您格式化字符串的选定部分。 有时文本的一部分是你无法控制的&#xff0c;也许它们来自数据库或…

为什么这么优秀的女生要找男程序员做老公?

这篇文章呢我们谈一下 学计算机的男生这个问题 这个话题主要是来自于 有一个舞蹈老师 有一天跟我聊起来 说他的一个学生 长得非常漂亮是个女士 身材非常棒然后 在这边就是在温哥华这边呢 正在申请PR这个是没有问题的 有工作然后就想找一个程序员 老公那就是这样的一个状态 我说…

文章生成器写出来的原创文章

文章生成机器人 文章生成机器人是一种基于人工智能技术和自然语言处理算法的程序&#xff0c;可以自动地生成高质量、原创的文章。 文章生成机器人的优点如下&#xff1a; 提高工作效率&#xff1a;文章生成机器人能够在较短的时间内自动帮助用户生成大量的文章&#xff0c;提…

JAVA数据结构之顺序表线性表的顺序查找,线性查找的两种方式------JAVA入门基础教程

//顺序查找,线性查找 //int[] arr1 new int[]{34,54,3,2,65,7,34,5,76,34,67}; //int target 5; //方式1boolean flag true; for (int i 0; i < arr1.length; i) {if(arr1[i] target){System.out.println("找到了在"i"位置");flag false;break;} …

编辑文件/文件夹权限 - Win系统

前言 我们经常会遇到由于权限不够无法删除文件/文件夹的情况&#xff0c;解决方案一般是编辑文件/文件夹的权限&#xff0c;使当前账户拥有文件的完全控制权限&#xff0c;然后再进行删除&#xff0c;下文介绍操作步骤。 修改权限 查看用户权限 右键文件/文件夹&#xff0c;…

【从零开始学Skynet】基础篇(四):网络模块常用API

游戏服务端要处理客户端请求&#xff0c;作为服务端引擎&#xff0c;网络编程也是Skynet的核心功能。1、学习网络模块 skynet.socket模块提供了网络编程的API&#xff0c;常用的API如下表所示&#xff1a;Lua API说明socket.listen(address ,port)监听一个端口&#xff0c;返回…

MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点1:sys.statement_analysis视图

文章目录MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点1&#xff1a;sys.statement_analysis视图视图sys.statement_analysis各列定义视图sys.statement_analysis视图的定义视图sys.statement_analysis各列解释例题例题解析参考MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点…

Java实现输入行数打印取缔字符,打印金字塔三角形的两个代码程序

目录 前言 一、实现输入行数&#xff0c;打印取缔字符 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图 二、打印金字塔三角形 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图​​​​​​​ 前言 1.因多重原因&#xff0c;本博文有…