我有以下问题:
我通过mmap和MAP_ANONYMOUS分配大量内存(多个MAP_ANONYMOUS)。该块包含一个大的散列映射,需要不时地对其进行零化。并不是每一轮都可以使用整个映射(不是每个页面都有故障),所以memset不是一个好主意--耗时太长。
快速做到这一点的最佳策略是什么?
将要
madvise(ptr, length, MADV_DONTNEED);保证以后的任何访问都会提供新的空页?
从Linux man madvise页面:
此调用不影响应用程序的语义( MADV_DONTNEED),除外),但可能会影响其性能。内核可以随意忽略这个建议。 ..。 MADV_DONTNEED 在此范围内的后续页面访问将成功,但将导致从底层映射文件(请参阅mmap(2))重新加载内存内容,或者对没有基础文件的映射进行零填充按需页。 ..。 当前的Linux实现(2.4.0)更多地将此系统调用视为命令而不是通知.
还是我必须重新绘制munmap并重新绘制该地区的地图?
它必须在Linux上工作,并且在OS上具有相同的行为。
发布于 2013-09-03 16:18:37
对于您的问题,有一个非常容易移植的解决方案:
mmap(ptr, length, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);由于MAP_FIXED由于特定于实现的原因而被允许失败,如果它返回MAP_FAILED,则返回MAP_FAILED是明智的。
发布于 2013-09-04 01:48:12
在Linux上,您可以依赖于匿名映射的MADV_DONTNEED将映射归零。不过,这并不是可移植的-- madvise()本身并不标准化。posix_madvise()是标准化的,但是POSIX_MADV_DONTNEED不具有与Linux MADV_DONTNEED标志相同的行为-- posix_madvise()始终是建议性的,并且不影响应用程序的语义。
发布于 2013-09-03 16:01:34
这种madvise行为当然是不标准的,因此这是不可移植的。
如果您想要的零碎部分恰好位于映射的末尾,那么您就可以使用ftruncate了。你得再多介绍一步:
shm_openftruncate达到所需大小mmap那你就可以一直
munmapftruncate到短小的东西ftruncate为您所需的实际长度mmap再一次然后,您“重新映射”的部分将为零初始化。
但也要记住,系统必须对页面进行零化。这可能比编译器为memset生成的内联内容更有效率,但这还不确定。
https://stackoverflow.com/questions/18595123
复制相似问题