惰性过量分配和 calloc

问题描述

知情人士能否解释一下延迟支持的堆存储如何与 calloc/realloc 的内存归零保证交互?具体来说,我想知道:

  1. 如果/当零写入会导致存储立即出现故障
  2. 如果/如果不是,我是否应该关注可能发生故障的上下文(例如,从程序集完成的读取系统调用)

解决方法

calloc 可以从操作系统获得保证为零的页面,从而完全避免在用户空间中写入零。 (特别是对于大型分配,否则如果有任何大小合适的空闲列表条目,它会将空闲列表中的某些内容归零。)这就是懒惰的来源。

因此您的页面将从 mmap(MAP_ANONYMOUS) 新鲜出炉,不会受到用户空间的影响。读取它会触发一个软页面错误,写时复制将它映射到一个共享的物理页面零。 (非常有趣的事实,当在巨大的 calloc 分配上进行只读循环时,您可能会遇到 TLB 未命中但 L1d/L2 缓存命中。

写入该页面/其中一个页面(作为第一次访问,或者在 CoW 映射到零页面之后)将软页面错误,Linux 的页面错误处理程序将分配一个新的物理页面和零它。 (所以在缺页之后,整个页面通常在 L1d 缓存中是热的,或者至少是 L2,即使有 faultaround 准备更多的页面并将它们连接到页表中以减少页面错误的数量,如果有相邻的页面也是懒惰分配的)。


但是不,除了一般的性能调整之外,您通常不需要担心它。如果您在逻辑上拥有一些内存,您可以要求 read 将数据放入其中。 libc 包装器没有在那里做任何特殊的重试;所有的魔法(检查目标页面是否存在并将其处理为软或硬页面错误)发生在内核的 read 实现中,作为 copy_to_user 的一部分。

(基本上是一个从内核内存到用户空间的 memcpy,如果你向内核传递一个你甚至不逻辑拥有的指针,通过权限检查可以使它返回 -EFAULT . 即如果您从用户空间触摸它就会出现段错误的内存。请注意,您不会从 read(0,NULL,1) 获得 SIGSEGV,只是一个错误。使用 strace ./a.out 来查看,作为实际实现的替代方法在您的手写 asm 中进行错误检查。)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...