深入浅出mmap内存映射

一、mmap内存映射主要用在哪里

mmap内存映射是一种将文件或其他对象映射到进程地址空间的机制,主要用于以下场景:

1. 文件映射:在许多操作系统中,可以通过mmap将一个文件的整个内容映射到进程的地址空间中。这种技术被广泛应用于一些高效的文件操作,如数据库系统,谷歌的大量的Web服务器和开发一些离线处理的大数据应用。

2. 共享内存:mmap还可以将一块共享内存映射到多个进程的地址空间中,这些进程可以直接通过访问共享内存来交换数据,可以在这些进程间实现高效的通信。

3. 匿名映射:通过mmap可以在进程的地址空间中分配一块虚拟内存,来实现不同进程之间的数据共享,这种匿名映射的内存映射技术被广泛应用于Unix/Linux系统中的共享库,而且在现代操作系统中也是非常有用的。

二、mmap内存映射函数的参数

mmap函数在使用时需要传递四个必要的参数,它们依次是:

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

1. addr:可选的指定映射的开始地址,通常将它设置为0,让系统自动选择一个未使用的地址作为映射的地址,这是一个好的习惯。

2. length:映射的大小,单位是字节。

3. prot:映射区域的保护方式,可以是下面几个选项中的一个或多个组合:

  • PROT_EXEC:表示可执行的代码
  • PROT_READ:表示可读
  • PROT_WRITE:表示可写
  • PROT_NONE:表示不可访问

4. flags:控制映射区域的各种属性,可以通过以下的选项进行组合:

  • MAP_PRIVATE:建立一个写入时拷贝(COW)的私有映射,不会改变原对象。
  • MAP_SHARED:对映射区域的写入数据会复制回文件

5. fd:需要映射的文件描述符。

6. offset:文件映射的偏移量,通常将它设置为0,表示从文件头开始。

三、mmap内存映射原理

mmap内存映射是基于虚拟内存进行的,它允许应用程序像访问内存一样访问磁盘上的文件,实际上是将文件的一段内容直接映射到进程地址空间的一段区域中,这导致了一系列的优点:

  • 有时不需要将整个文件都读入内存即可开始工作
  • 当需要更新文件时,不需要显式地拷贝到磁盘上
  • 不会造成page cache的污染,同时内存限制也大大增加

它的底层实现利用了虚拟内存的一个非常重要的好处,即虚拟内存能够将物理内存和交换空间(磁盘)组合在一起使用。CPU需要访问进程的某个虚拟地址时,会计算出这个地址在物理内存或者磁盘上的位置,如果在物理内存上,那么直接访问;否则就会将物理内存中不常用的页替换到磁盘上,然后再从磁盘上读入需要的页。

四、mmap内存映射内核

mmap内存映射是由操作系统内核虚拟内存系统的具体实现来支持的。具体来说,内核在mmap函数调用时,会向虚拟内存子系统发送一个请求,让它将一个虚拟内存区域映射到用户进程的地址空间中。当进程访问这个虚拟内存区域时,虚拟内存子系统会将对应的数据从文件中读入,或者将数据写回磁盘上。

这个虚拟内存区域是由用户进程管理的,称为内存映射区域。在虚拟内存系统中,被映射文件的每一个页都有多个副本,既可以在文件中存在,也可以在内存中存在。因此,当进程对一个虚拟内存区域中的某个页进行访问时,虚拟内存系统会将这个页映射到多个虚拟内存区域中,并将这些虚拟内存区域转换为物理页框,使得这些虚拟内存区域实际上都指向了同一个物理页。

五、mmap内存映射大小限制

在64位系统中,由于地址空间的大小可以达到2^64个字节,因此可以创建非常大的内存映射区域。但是在32位系统中,由于地址空间的大小只有2^32个字节,因此内存映射的大小受到了一定的限制,在一些系统中可以定义一些参数来调整限制的大小。

六、mmap内存映射 文件为空

当被映射的文件为空时,根据函数的flags参数的不同,mmap内存映射的行为也有所不同。

1. 如果标志选项包含MAP_PRIVATE,则映射区域中的内容将被初始化为0。

2. 如果标志选项包含MAP_SHARED,则映射区域的是未定义的,并且对该区域的访问会产生总线错误(bus error)。

七、mmap内存映射bus error

当mmap映射区域为空时,在对映射区域进行写入等操作时,会产生总线错误(bus error)。这是因为在尝试使用空的映射区域时,访问的内存地址无效。这时可以使用mmap函数的MAP_ANONYMOUS参数来初始化该映射区,例如:

char *ptr = mmap(NULL, sizeof(char)*512, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);

这样就可以正确初始化一个空的映射区域了。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/287209.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-23 13:07
下一篇 2024-12-23 13:07

相关推荐

  • Python创建分配内存的方法

    在python中,我们常常需要创建并分配内存来存储数据。不同的类型和数据结构可能需要不同的方法来分配内存。本文将从多个方面介绍Python创建分配内存的方法,包括列表、元组、字典、…

    编程 2025-04-29
  • Python变量在内存中的存储

    该文章将从多个方面对Python变量在内存中的存储进行详细阐述,包括变量的声明和赋值、变量的引用和指向、内存地址的变化、内存管理机制等。 一、声明和赋值 在Python中,变量声明…

    编程 2025-04-29
  • Python计算内存占用

    Python是一种高级的、解释性的、面向对象的、动态的程序语言,因其易于学习、易于阅读、可移植性好等优点,越来越受到开发者的青睐。当我们编写Python代码时,可能经常需要计算程序…

    编程 2025-04-28
  • 使用Go-Redis获取Redis集群内存使用率

    本文旨在介绍如何使用Go-Redis获取Redis集群的内存使用率。 一、Go-Redis简介 Go-Redis是一个用于连接Redis服务器的Golang客户端。它支持Redis…

    编程 2025-04-28
  • Python mmap共享使用指南

    Python的mmap模块提供了一种将文件映射到内存中的方法,从而可以更快地进行文件和内存之间的读写操作。本文将以Python mmap共享为中心,从多个方面对其进行详细的阐述和讲…

    编程 2025-04-27
  • Python内置函数——查看对象内存

    本文将介绍Python内置函数中,在开发中查看对象内存的相关函数。 一、id()函数 id()函数是Python内置函数,用于返回对象的唯一标识符,也就是对象在内存中的地址。 nu…

    编程 2025-04-27
  • Python进程池共享内存用法介绍

    本文将从多个方面详细阐述Python进程池共享内存的相关知识,包括如何使用进程池、进程池的实现原理、进程池中的共享内存管理等。本文内容将涵盖: 一、进程池的使用 进程池是一种有效的…

    编程 2025-04-27
  • 深入浅出统计学

    统计学是一门关于收集、分析、解释和呈现数据的学科。它在各行各业都有广泛应用,包括社会科学、医学、自然科学、商业、经济学、政治学等等。深入浅出统计学是指想要学习统计学的人能够理解统计…

    编程 2025-04-25
  • 深入解析Redis内存淘汰策略

    Redis是一个高性能键值数据库,由于其快速、稳定和易于使用,它已经成为很多应用程序中不可或缺的一部分。在使用Redis时,我们需要考虑内存管理问题。Redis内存淘汰策略是如何工…

    编程 2025-04-25
  • 解决SQL Server内存占用高问题的方法

    一、关闭不必要的服务 在SQL Server安装时,默认开启了许多服务,包括SQL Server Browser,SQL Server Agent等。关闭不必要的服务可以释放内存资…

    编程 2025-04-25

发表回复

登录后才能评论