当前位置:首页 > 内存 > 正文

mmap内存映射读取更新慢

  • 内存
  • 2024-07-03 16:58:19
  • 6910

一、关于共享内存shm和内存映射mmap的区别是什么?


深入分析:共享内存shm与内存映射mmap的区别分析

内存映射,通过系统调用mmap(sys/mman.h),在进程中虚拟内存与物理内存或文件区域建立直接连接。它将处理区域划分为若干个有序的VMA(虚拟内存区域),包括代码段、数据段、堆、栈以及文件映射和动态链接库区域。每个映射区域都有独特的权限和管理方法。


核心机制


mmap的核心是基于structvm_area_struct的VMA管理,通过双向链表和红黑树实现高效搜索。它允许进程根据起始地址addr(可选,通常被忽略)和长度自动以页(4K)为单位配置VMA,通过fd和offset与文件关联。


进程的虚拟内存结构分为文件映射和匿名映射。前者通过fd和offset与文件系统交互,权限由prot和flag控制。BSS段、堆和堆栈使用匿名映射(无文件对应),权限通常为读取和写入。


共享和隐私是mmap的关键特性:共享(MAP_SHARED)允许进程之间的合作,私有(MAP_PRIVATE)确保据独占性。私有映射,例如MAP_PRIVATE|MAP_ANONYMOUS,用于请求大内存。当页面丢失时,内核会分配物理页面。


内核为load_binary等函数中的代码和数据段创建私有匿名映射,以隔离进程之间的修改。当进程尝试写入文件映射时,如果它是私有映射,则会触发新的物理内存分配。写操作仅限于内核维护的页缓冲区,不会直接写回磁盘。


大页内存映射


大页内存映射(例如MAP_HUGETLB)是提高性能的关键,尤其是在内存密集型应用程序中。Linux支持2M和1G大页,需要内核配置支持,通过/sys/kernel/mm/hugepages进行调整。透明大页(THP)由内核自动管理,会导致性能波动,因此应谨慎使用。


匿名映射和共享文件映射


匿名映射通过映射到匿名文件来实现父子进程之间的共享,而共享文件映射(MAP_SHARED)允许跨进程读写协作,更改将实时反映在所有映射中,并且通过页面缓存和内核的pdflush线程实现数据同步。


综上所述,mmap和shm在内存管理上有不同的侧重点:mmap提供灵活的映射选项,包括大页映射,而shm通常用于进程间通信的直接内存共享。。了解这些差异有助于优化程序性能和并发处理。



二、Linux中mmap()函数的内存映射问题理解?

深入理解Linux中mmap()函数的内存映射机制


在Linux世界中,mmap()函数就像一把神秘的钥匙,它打开了连接的锁内存和文件之间有直接的联系。让我们揭开这个功能的神秘面纱,看看它在内核级别是如何工作的。


首先我们放弃虚拟内存这一商业概念,它在开发中没有任何实际意义。从开发者的角度来看,我们关注的是虚拟空间,它是由进程看到的所有地址组成的广阔区域。虚拟空间是分配给进程(已分配和待分配)的所有物理地址的重新映射,它为我们提供了程序的执行阶段。


mmap的主要作用是允许应用程序直接访问工作内存等文件。虽然底层实现和性能优化是内核和驱动的责任,但作为开发者只需要关注它的功能,根据自己的需求灵活使用即可。不要过多关注技术细节,让它在您的代码中发挥作用。


现在让我们看看mmap是如何工作的。当你调用mmap时,内核会在你的虚拟空间中保留一个区域,但不会立即分配物理内存。当您尝试访问该空间时,处理器将抛出异常。此时,内核会动态分配物理内存,插入文件内容,然后返回给你的程序。只有这样你才会意识到数据的存在。


至于驱动的页面读取策略和内存分配算,这些是内核内部决定的,编程时不考虑。请记住,mmap的重点是方便,而不是详尽的细节,因此不要太有想象力。


至于交换分区,通过深入理解《Linux内存管理的奥秘》这篇文章,可以掌握它在内存管理中的作用。明白了这一点,你就可以更好地理解为什么我建议用虚拟空间的概念来代替虚拟内存了。


内存是计算机的主要组成部分,由DRAM组成,用于存储数据。为了访问内存,我们为其分配地址,这些地址的集合构成了内存空间。物理地址空间包括内存和I/O,其大小受到地址总线长度的限制,可以远大于DRAM的实际容量。


CPU访问内存时,MMU(内存管理单元)进行地址转换,将虚拟地址映射到物理地址。虚拟地址空间和指令集地址长度可能不一致。例如,64位处理器可以访问64位地址,但地址总线只能是48位。这意味着虚拟空间可以很大,但物理内存不一定要匹配。


每个进程都有一个独立的虚拟空间,可以映射到物理内存中的不同位置。Linux运行程序时,会使用mmap将程序加载到内存中,从而将虚拟空间与文件内容关联起来,像这样:


这个过程看起来很简单,但文件内容实际上存储在磁盘上,CPU无法直接访问。当执行操作时,内核会引发异常,并将文件内容从磁盘加载到物理内存中,形成动态内存映射。


可以在/proc/pid/maps文件中查看进程的内存映射状态,如init进程的映射状态。这些映射的某些区域与称为积压文件的文件相关联,这些文件在内存不足时从磁盘加载数据;没有文件关联内存的内存,例如通过brk或malloc动态分配的内存,称为匿名内存。它可以与交换文件关联,提供扩展内存的可能性。


最后,如果想删除缓存,可以使用/proc/sys/vm/drop_caches命令或者在挂载时指定sync或dirsync参数。但是,请务必谨慎操作,以避免影响系统性能。


通过上面的深入分析,你应该对Linux的mmap函数及其内存映射机制有了更清晰的了解。现在您可以放心地在代码中使用这个强大的工具来实现高效的文件映射操作。

上一篇:文件内存映射

下一篇:内存映射概念