fie*_*sor 5 linux macos posix memory-management mmap
我正在编写一个内存分配例程,目前运行顺利。我使用 4096 字节页面中的 mmap() 从操作系统获取内存。当我启动我的内存分配器时,我用 mmap() 分配了 1gig 的虚拟地址空间,然后在进行分配时,我根据我的分配算法的细节将其划分为大块。
我觉得一时兴起分配多达 1gig 的内存是安全的,因为我知道 mmap() 实际上并没有将页面放入物理内存中,直到我实际写入它们。
现在,使用我的分配器的程序可能会突然出现需要大量内存的情况,在这种情况下,操作系统最终必须将整个 1gig 的页面放入物理 RAM 中。问题是程序可能会进入休眠期,在此期间它会释放大部分 1gig,然后仅使用最少量的内存。然而,我在分配器的 MyFree() 函数中真正做的就是翻转一些簿记数据,这些数据将以前使用的演出标记为空闲,但我知道这不会导致操作系统从物理内存中删除这些页面。
我不能使用像 munmap() 这样的东西来解决这个问题,因为分配算法的本质是它需要一个连续的内存区域,没有任何漏洞。基本上我需要一种方法来告诉操作系统“听着,您可以将这些页面从物理内存中取出并将它们清除为 0,但是当我再次需要它们时,请立即重新映射它们,就好像它们是新的 mmap() 一样” ”
解决这个问题的最佳方法是什么?
实际上,在写完这些之后,我才意识到我可能可以先执行 munmap(),然后立即执行新的 mmap()。这是正确的方法吗?我觉得可能有一些更有效的方法来做到这一点。
您正在寻找madvise(addr, length, MADV_DONTNEED). 从联机帮助页:
MADV_DONTNEED:预计近期不会访问。(目前,应用程序已完成给定范围,因此内核可以释放与其关联的资源。)对该范围内的页面的后续访问将成功,但将导致从底层映射重新加载内存内容文件(请参阅 mmap(2))或按需填零页面以获取没有底层文件的映射。
特别注意有关后续访问如何成功但恢复到按需填零(对于没有底层文件的映射)的语言。
您大声思考的替代方案(munmap紧随其后的是另一个)mmap也可以工作,但存在内核端效率低下的风险,因为它不再跟踪单个连续区域的分配;如果有很多这样的取消映射和重新映射事件,内核端数据结构可能会变得非常臃肿。
顺便说一句,对于这种分配器,用于MAP_NORESERVE初始分配非常重要,然后在分配时触摸每个页面,并捕获任何结果SIGSEGV并使分配失败。(并且您需要记录您的分配器安装了一个处理程序SIGSEGV。)如果您不这样做,您的应用程序将无法在禁用内存过量使用的系统上运行。有关更多详细信息,请参阅mmap联机帮助页。
| 归档时间: |
|
| 查看次数: |
905 次 |
| 最近记录: |