linux – mmap():将旧内存重置为零非驻留状态教程
我正在写一个内存分配例程,它目前正在顺利运行.我用4096字节页面中的mmap()从操作系统中获取内存.当我启动内存分配器时,我使用mmap()分配1gig的虚拟地址空间,然后在分配时根据我的分配算法的具体情况将其分成多个.
我觉得安心分配多达1gig的内存是因为我知道mmap()实际上并没有将页面放入物理内存,直到我真正写入它们.
现在,使用我的分配器的程序可能会急需它需要大量内存,在这种情况下,操作系统最终必须将整个1gig的页面放入物理RAM.问题是该程序可能会进入休眠期,在该期间释放大部分1gig,然后仅使用最少量的内存.然而,我在分配器的MyFree()函数中真正做的就是翻转一些簿记数据,这些数据将之前使用的gig标记为空闲,但我知道这并不会导致操作系统从物理内存中删除这些页面.
我不能使用类似munmap()的东西来解决这个问题,因为分配算法的本质是它需要一个连续的内存区域而没有任何漏洞.基本上我需要一种方法来告诉操作系统“听,你可以将这些页面从物理内存中取出并清除它们,但是当我再次需要它们时请立即重新映射它们,好像它们是新鲜的mmap()”d “
最好的方法是什么?
实际上,在写完这一切之后我才意识到我可以做一个munmap(),紧接着是一个新的mmap().这是正确的方法吗?我觉得可能有一些更有效的方法来做到这一点.
解决方法:
您正在寻找madvise(addr,length,MADV\_DONTNEED).从the manpage开始:
MADV\_DONTNEED: Do not expect access in the near future. (For the time being, the application is finished with the given range, so the kernel can free resources associated with it.) Subsequent accesses of pages in this range will succeed, but will result either in reloading of the memory contents from the underlying mapped file (see mmap(2)) or zero-fill-on-demand pages for mappings without an underlying file.
请特别注意有关后续访问如何成功但返回零填充按需的语言(对于没有底层文件的映射).
你对另一个mmap紧随其后的munmap的思维大声的替代方案也会起作用,但是由于它不再跟踪单个连续区域的分配,因此存在内核方面效率低下的风险;如果有许多这样的unmap-and-remap事件,那么内核数据结构可能会变得非常臃肿.
顺便说一下,使用这种分配器,使用MAP\_NORESERVE进行初始分配非常重要,然后在分配时触摸每个页面,并捕获任何生成的SIGSEGV并使分配失败. (并且您需要记录您的分配器为SIGSEGV安装处理程序.)如果您不这样做,您的应用程序将无法在已禁用内存过量使用的系统上运行.有关更多详细信息,请参见mmap联机帮助页.