首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用“`madvise`”实现大内存映射的零

用“`madvise`”实现大内存映射的零
EN

Stack Overflow用户
提问于 2013-09-03 14:41:28
回答 3查看 3.6K关注 0票数 9

我有以下问题:

我通过mmapMAP_ANONYMOUS分配大量内存(多个MAP_ANONYMOUS)。该块包含一个大的散列映射,需要不时地对其进行零化。并不是每一轮都可以使用整个映射(不是每个页面都有故障),所以memset不是一个好主意--耗时太长。

快速做到这一点的最佳策略是什么?

将要

代码语言:javascript
复制
madvise(ptr, length, MADV_DONTNEED);

保证以后的任何访问都会提供新的空页?

从Linux man madvise页面:

此调用不影响应用程序的语义( MADV_DONTNEED),除外),但可能会影响其性能。内核可以随意忽略这个建议。 ..。 MADV_DONTNEED 在此范围内的后续页面访问将成功,但将导致从底层映射文件(请参阅mmap(2))重新加载内存内容,或者对没有基础文件的映射进行零填充按需页。 ..。 当前的Linux实现(2.4.0)更多地将此系统调用视为命令而不是通知.

还是我必须重新绘制munmap并重新绘制该地区的地图?

它必须在Linux上工作,并且在OS上具有相同的行为。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-09-03 16:18:37

对于您的问题,有一个非常容易移植的解决方案:

代码语言:javascript
复制
mmap(ptr, length, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

由于MAP_FIXED由于特定于实现的原因而被允许失败,如果它返回MAP_FAILED,则返回MAP_FAILED是明智的。

票数 9
EN

Stack Overflow用户

发布于 2013-09-04 01:48:12

在Linux上,您可以依赖于匿名映射的MADV_DONTNEED将映射归零。不过,这并不是可移植的-- madvise()本身并不标准化。posix_madvise()是标准化的,但是POSIX_MADV_DONTNEED不具有与Linux MADV_DONTNEED标志相同的行为-- posix_madvise()始终是建议性的,并且不影响应用程序的语义。

票数 2
EN

Stack Overflow用户

发布于 2013-09-03 16:01:34

这种madvise行为当然是不标准的,因此这是不可移植的。

如果您想要的零碎部分恰好位于映射的末尾,那么您就可以使用ftruncate了。你得再多介绍一步:

  1. 对数据具有“持久”文件描述符的shm_open
  2. ftruncate达到所需大小
  3. 那个FD的mmap

那你就可以一直

  1. munmap
  2. ftruncate到短小的东西
  3. ftruncate为您所需的实际长度
  4. mmap再一次

然后,您“重新映射”的部分将为零初始化。

但也要记住,系统必须对页面进行零化。这可能比编译器为memset生成的内联内容更有效率,但这还不确定。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18595123

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档