Linux non-persistent backing store for mmap()

Linux non-persistent backing store for mmap()

本文关键字:mmap for store non-persistent backing Linux      更新时间:2023-10-16

首先,一些激励性的背景信息:我有一个基于C++的服务器进程,该进程在基于ARM/Linux的嵌入式计算机上运行。 它运行良好,但作为其操作的一部分,它会创建一个相当大的固定大小的临时/非持久状态信息数组(例如数十到数百兆字节(,它当前将其保存在堆中,并且它会不时访问和/或更新该数据。

我正在调查我可以在多大程度上扩展事情,我遇到的一个问题是,最终(当我通过使其配置越来越大来对服务器进行压力测试时(,这种数据结构变得足够大,导致内存不足问题,然后 OOM 杀手出现,随之而来的是普遍的不满。 请注意,Linux 的这种嵌入式配置没有启用交换,我无法(轻松(启用交换分区。

关于如何改善这个问题,我有一个想法是将这个大数组分配给计算机的本地闪存分区,而不是直接在 RAM 中,然后使用 mmap(( 使服务器进程看起来就像它仍在 RAM 中一样。 这将大大减少RAM的使用,我希望Linux的文件系统缓存能够掩盖大部分由此产生的性能成本。

我唯一真正关心的是文件管理 - 特别是,我想避免任何用"孤儿"备份存储文件填充闪存驱动器的机会(即进程不再存在的旧文件,但文件仍然存在,因为它的创建过程崩溃或由于其他错误忘记在退出时删除它(。 我还希望能够在同一台计算机上同时运行服务器的多个实例,而这些实例不会相互干扰。

我的问题是,Linux是否有任何内置的工具来处理这种用例? 我特别想象某种方法来标记文件(或 mmap(( 句柄或类似(,以便当创建进程的文件退出或崩溃时,操作系统会自动删除该文件(类似于 Linux 已经自动恢复进程分配的所有 RAM 的方式,当进程退出或崩溃时(。

或者,如果 Linux 没有任何内置的自动临时文件清理功能,人们是否使用"最佳实践"来确保大型临时文件不会因无意中变得持久而最终填满驱动器?

请注意,AFAICT 简单地将文件放在/tmp 中对我没有帮助,因为/tmp 使用的是 RAM 磁盘,因此与简单地分配进程内堆存储相比,它不会给我带来任何 RAM 使用优势。

是的,我一直这样做...

open文件,unlink它,使用ftruncate或(更好的(posix_fallocate使其大小合适,然后将mmapMAP_SHARED一起使用以将其映射到地址空间。然后,如果需要,您可以立即close描述符;内存映射本身将保留文件。

为了提高速度,您可能会发现您想帮助 Linux 管理其页面缓存。您可以将posix_madvisePOSIX_MADV_WILLNEED一起使用来建议内核对数据进行页面处理,POSIX_MADV_DONTNEED建议内核释放页面。

您可能会发现最后一个不能按您想要的方式工作,尤其是对于脏页面。您可以使用sync_file_range显式控制刷新到磁盘。(尽管在这种情况下,您需要保持文件描述符打开。

所有这些都是完全标准的POSIX,除了Linux特定的sync_file_range

是的,您创建/打开文件。然后,按文件名remove()文件。

该文件仍将由您的进程打开,您可以像任何打开的文件一样读取/写入它,并且当打开文件的进程退出时,它将消失。

我相信这种行为是由posix强制要求的,所以它可以在任何类似Unix的系统上运行。即使在硬重启时,空间也会被回收。

我相信这是特定于文件系统的,但大多数 Linux 文件系统允许删除打开的文件。该文件将仍然存在,直到关闭它的最后一个句柄。我建议您打开该文件,然后立即将其删除,当您的进程因任何原因退出时,它将自动清理。

有关更多详细信息,请参阅这篇文章:如果指向的文件被移动,Linux 上的打开文件句柄会发生什么情况,删除