l.k*_*l.k 1 c linux assembly calloc page-fault
知道的人可以解释一下延迟支持的堆存储如何与 calloc/realloc 的内存归零保证交互吗?具体来说,我想知道:
calloc
可以从操作系统获得保证为零的页面,从而完全避免在用户空间中写入零。(特别是对于大型分配,否则如果有任何大小合适的空闲列表条目,它将从空闲列表中清零。)这就是懒惰的来源。
所以你的页面将是新鲜的mmap(MAP_ANONYMOUS)
,不受用户空间的影响。读取它会触发一个软页面错误,即写时复制将它映射到一个共享的物理页面零。(非常有趣的事实,当在巨大的 calloc 分配上以只读方式循环时,您可能会遇到 TLB 未命中但 L1d/L2 缓存命中)。
写入该页面/其中一个页面(作为第一次访问,或者在它被 CoW 映射到零页面之后)将软页面错误,并且 Linux 的页面错误处理程序将分配一个新的物理页面并将其归零。(所以在缺页之后,整个页面通常在 L1d 缓存中是热的,或者至少是 L2,即使有 faultaround 准备更多的页面并将它们连接到页表中以减少页面错误的数量,如果有相邻的页面也被懒惰地分配)。
但是不,除了一般的性能调整之外,您通常不需要担心它。如果您在逻辑上拥有一些内存,您可以要求read
将数据放入其中。libc 包装器没有在那里做任何特殊的重试;所有的魔法(检查目标页面存在和对待它就像一个软或硬页面错误)发生在内核的实现里面read
,作为其一部分copy_to_user
。
(基本上是从内核内存到用户空间的 memcpy,-EFAULT
如果您向内核传递一个您甚至在逻辑上都不拥有的指针,则可以通过权限检查使其返回。即,如果您从用户空间触摸它,则会出现段错误的内存。请注意,您不会从 获得 SIGSEGV read(0, NULL, 1)
,只是一个错误。strace ./a.out
用于查看,作为在您的手写 asm 中实际实现错误检查的替代方法。)