Unix内存映射

在Unix系统中,文件映射是一种将磁盘文件与内存区域关联起来的技术。其基本原理是,通过操作系统提供的内存管理设施,将文件的一部分或全部直接映射到进程的地址空间。

当程序访问这段内存区域时,实际上就是在访问文件的内容。这在很多场景中都是非常有用的。 比如说,假设你正在运行一个文本编辑器,需要打开一个非常大的文件进行编辑。传统的做法是,通过读操作将文件内容读入内存缓冲区,然后进行处理。但如果文件非常大,比如几个G,那么这种方式将消耗大量的内存和I/O资源。更重要的是,每次编辑器对文件的修改,都必须把完整的文件内容重新写回磁盘,以确保数据的一致性,这将会极大地影响程序的性能。 通过文件映射,编辑器可以将文件内容直接映射到内存中,将文件视为一个大数组。程序可以直接读写这段内存,从而读写文件内容。当修改文件时,只修改了内存中的一小部分,操作系统会负责将这部分数据写回磁盘,而不需要重新写入整个文件。这样既减少了内存消耗,又优化了I/O操作,提高了程序的性能。 此外,文件映射还可以用于进程间通信(IPC)。通过将同一个文件映射到不同的进程内存空间中,这些进程就可以通过访问和修改这段共享内存,来交换数据和同步状态。 所以,Unix中的文件映射在很多不同的场合下都有其强大的作用。

如图: 说明了虚拟地址与物理地址通过页来建立联系

我们使用mmap函数来创建映射:

使用案例:

cpp 复制代码
#include<t_stdio.h>
#include <sys/mman.h>
#include<string.h>
int main(void){
 // 将物理地址映射到虚拟地址空间
  int prot = PROT_READ | PROT_WRITE;
  int flags = MAP_PRIVATE |  MAP_ANONYMOUS;
 void * p= mmap(NULL,1024,prot ,flags,-1 ,0);
 if(p==MAP_FAILED) E_MSG("mmap",-1);
 // 这里已经将物理地址映射进程的虚拟地址空间
 strcpy(p,"hello beijing");
 printf("%s..\n",(char *)p);
 //解除映射
        munmap(p,1024);
return 0;
}

这是一个使用了内存映射(memory mapping)的C程序。该程序的目标是在虚拟内存空间中分配一段空间,然后在这段空间中写入字符串,最后释放这段内存空间。下面是关于这个进程的详细解释: 首先,必须要包含的头文件有 <t_stdio.h><sys/mman.h><string.h> 。其中, <sys/mman.h> 包含内存映射相关的函数,如 mmapmunmap,而 <string.h> 包含字符串操作的函数,如 strcpy。 函数开始时,它定义了两个整型变量 protflags 分别表示 protection 和 flags,用于控制内存映射的属性。 接着是 void* p = mmap(NULL, 1024, prot, flags, -1, 0);,这是一个 mmap 系统调用的使用,主要功能是在内存中创建一个映射。以下是这个函数参数的含义:

  • NULL 指明让系统自动选择映射的虚拟地址。
  • 1024 是请求映射的内存大小。
  • prot 定义了这个映射的权限,包括读取(PROT_READ)和写入(PROT_WRITE)权限。
  • flags 定义了其他选项,例如 MAP_PRIVATE 表示创建一个改变不会写回底层文件的私有映射, MAP_ANONYMOUS 表示映射不关联任何文件,忽略下面两个参数。
  • -1 这个参数会被忽略,因为使用了 MAP_ANONYMOUS
  • 0 指该内存段从物理文件的哪个位置开始映射,这同样会被忽略。 如果映射失败,mmap会返回 MAP_FAILED,程序将报错并结束。 如果映射成功,mmap 返回映射区域的起始地址,然后就可以在这块区域进行操作了。strcpy(p, "hello beijing"); 是在这块内存中写入字符串 "hello beijing"。然后 printf("%s",(char*)p); 将该内存区域的内容作为字符串打印出来。 最后,munmap(p, 1024); 调用解除映射,释放之前映射的内存空间。 总结一下,这个程序主要是演示如何使用 mmap 函数在内存中创建一个映射区域,用于存储字符串,并打印出来,然后释放这片内存区域。
相关推荐
FJW02081415 分钟前
【Linux】web服务器的部署和优化
linux·运维·服务器·rhce
Linux运维老纪22 分钟前
Python文件操作及数据库交互(Python File Manipulation and Database Interaction)
linux·服务器·数据库·python·云计算·运维开发
平生不喜凡桃李34 分钟前
Linux 进程控制
linux·运维·服务器
鱼与宇1 小时前
Linux常用命令
linux·运维·服务器
小南家的青蛙1 小时前
lspci的资料
linux·运维·服务器
饭来_3 小时前
配置 RDP 远程桌面协议连接ubuntu服务器桌面
linux·运维·服务器
古德赖可可3 小时前
linux的例行性工作(at)
linux·运维·服务器
猪猪侠|ZZXia4 小时前
# 家庭网络IPv6地址的一些知识
linux·运维·服务器·网络·智能路由器
hgdlip4 小时前
网易云音乐如何查看ip属地?详细操作指南
服务器·网络·tcp/ip·网易云
小王努力学编程4 小时前
【Linux网络编程】应用层协议HTTP(实现一个简单的http服务)
linux·服务器·网络·c++·网络协议·学习·http