我正在尝试为无交换系统实现文件支持的内存分配器。
对于每个新分配,我使用mkstemp
创建一个临时文件作为后备存储,mmap
将其创建为MAP_SHARED
,以便在系统内存压力很高时允许将页面交换到该后备存储中。我想我已经完成了这一部分。
但是我在实施解除分配案件时遇到困难。
由于在重新分配时,后台存储的内容,驻留页面或脏页面的内容都不再重要,因此,最快的方法是删除并释放所有驻留页面并保持后台存储不变。但是我没有找到可以做到这一点的madvice
标志。
MADV_DONTNEED
似乎过多,因为它会将脏页提交到后存储。 (不正确,请参见下面的答案)
MADV_DONTNEED
成功执行MADV_DONTNEED操作后,将更改指定区域中的内存访问的语义:后续对该范围内的页面的访问将成功,但是将导致从最新的内容中重新填充内存内容。基础映射文件(用于共享文件映射,共享匿名映射以及基于shmem的技术,例如System V共享内存段)或用于匿名私有映射的按需填充零页面。
MADV_REMOVE
似乎也过多,因为它不仅会删除常驻页面,而且还会删除后台存储本身。
MADV_REMOVE
释放给定范围的页面及其关联的后备存储。这等效于在后备存储的相应字节范围内打一个洞(请参见fallocate(2))。在指定地址范围内的后续访问将看到包含零的字节。
那么取消映射/关闭/删除mmap
文件的最快步骤是什么?
也许mmap
与MAP_PRIVATE
(like this)再次相同,然后又munmap
吗?
答案 0 :(得分:1)
根据this question,return (x1 > x2) ? ((x1 > x3)?
x1 :
x3) :
(x2 > x3) ? x2 : x3;
确实做到了这一点:删除页面而不写回后台存储。
子句if
表示MADV_DONTNEED
之后的加载将从后台存储重新加载。
repopulating the memory contents from the up-to-date contents of the underlying mapped file
之前的所有脏页都没有提交到后备存储,因此将丢失。
总而言之:MADV_DONTNEED
删除所有映射的页面(包括脏页面未提交到后备存储器),并按原样保留后备存储器。
答案 1 :(得分:0)
在脏页上疯狂地MADV_DONTNEED不会放弃所做的更改。
我刚刚使用mmap / madvise MADV_DONTNEED / munmap编写了一个5GB的文件,最后2个步骤以2-4MB的块进行,并且该文件的创建没有一个错误。
但是MADV_DONTNEED对脏页没有影响。 munmap减少了该过程的RSS,但仍由Linux自行决定编写。