匿名mmap零填充?

时间:2013-07-09 03:42:13

标签: memory freebsd mmap

In Linux, the mmap(2) man page解释了匿名映射

  

。 。 。没有任何文件支持;其内容初始化为零。

The FreeBSD mmap(2) man page没有对零填充做出类似的保证,尽管它确实保证非匿名映射中文件结尾后的字节为零填充。

哪种Unix承诺从匿名mmaps返回零初始化内存?哪些在实践中返回零初始化内存,但在他们的手册页上没有做出这样的承诺?

我的印象是零填充部分是出于安全原因。我想知道是否有任何mmap实现跳过对mmap,munmap,然后由单个进程再次mmapped的页面的零填充,或者如果任何实现用伪随机位填充新映射的页面,或者某些非零常量。

P.S。 Apparently, even brk and sbrk used to guarantee zero-filled pages.我在Linux上的实验似乎表明,即使在sbrk调用分配它们之后页面错误时填满了整页,部分页面也不会:

#include <unistd.h>
#include <stdio.h>

int main() {
  const intptr_t many = 100;
  char * start = sbrk(0);
  sbrk(many);
  for (intptr_t i = 0; i < many; ++i) {
    start[i] = 0xff;
  }
  printf("%d\n",(int)start[many/2]);
  sbrk(many/-2);
  sbrk(many/2);
  printf("%d\n",(int)start[many/2]);
  sbrk(-1 * many);
  sbrk(many/2);
  printf("%d\n",(int)start[0]);
}

2 个答案:

答案 0 :(得分:7)

如果没有简单地详尽列举所有手册页或其他发布文档,很难说哪些承诺是什么,但处理MAP_ANON的底层代码(通常?总是?)也用于在bss空间中映射可执行文件和bss空间需要填零。所以这很可能。

至于“给你回旧的价值”(或者一些非零值,但很可能是你的旧值),如果你取消映射并重新映射,如果某些系统是“懒惰的”,这似乎是可能的关于解除分配。我首先只使用了一些支持mmap的系统(BSD和Linux衍生产品),而且这两种系统都不是那么懒,至少在内核代码处理mmap中没有。

sbrk可能会或可能不会填充“重新生成”页面的原因可能与历史记录或缺乏历史记录有关。当前的FreeBSD代码与我在旧mmap天之前回忆的内容相匹配:有两个半秘密变量,minbrkcurbrk,以及brksbrk只会在SYS_break移动到至少为curbrk的值时调用minbrk(真正的系统调用)。 (实际上,这看起来有点破碎:brk具有至少行为,但sbrk只是将其参数添加到curbrk并调用SYS_break。由于内核检查,似乎无害sys_obreak()位于/sys/vm/vm_unix.c,因此过于负面的sbrk()会因EINVAL而失败。)

我必须查看Linux C库(然后也可能是内核代码),但它可能只是忽略“降低中断”的尝试,而只是在libc中记录“逻辑中断”值。如果您有mmap()且没有向后兼容性要求,则可以使用匿名映射在libc中完全实现brk()sbrk(),并且将它们实现为“增长”将是微不足道的。只是“,就像它一样。”

答案 1 :(得分:1)

哪种类型的Unix承诺从匿名mmap返回零初始化的内存?

GNU / Linux

正如您在问题中所说,Linux version of mmap承诺零填充匿名映射:

MAP_ANONYMOUS

映射没有任何文件支持;其内容初始化为零。

NetBSD

NetBSD version of mmap承诺零填充匿名映射:

MAP_ANON

映射匿名内存,该内存不与任何特定文件关联。文件描述符不用于创建MAP_ANON区域,而必须指定为-1。映射的内存将为零。

OpenBSD

OpenBSD manpage of mmap不承诺将零填充匿名映射。但是,Theo de Raadt(著名的OpenBSD开发人员)在November 2019 on the OpenBSD mailing list中声明:

当然是零填充。还有什么呢?没有任何可行的选择。

我认为这很明显地削弱了消息的其余部分。

其他OpenBSD开发人员并不与他矛盾。

IBM AIX

AIX version of mmap承诺零填充匿名映射:

MAP_ANONYMOUS

指定创建一个初始化为全零的新的匿名内存区域。

HP-UX

根据nixdoc.net,HP-UX version of mmap承诺零填充匿名映射:

如果在MAP_ANONYMOUS中设置了flags,则会创建一个新的内存区域并将其初始化为全零。

Solaris

Solaris version of mmap承诺零填充匿名映射:

MAP_ANON中设置flags,并且将fildes设置为-1时,mmap()提供了将匿名页面返回给调用者的直接路径。此操作等效于在{{1}上通过mmap()参数省略/dev/zeroMAP_ANON上向flags传递打开文件描述符。

此Solaris手册页为我们提供了一种获取零填充内存页面的方法,而无需依靠与MAP_ANONYMOUS标志一起使用的mmap的行为:请勿使用MAP_ANONYMOUS标志并创建映射由/dev/zero文件支持。了解提供/dev/zero文件的类Unix操作系统列表,以查看这种方法是否比使用MAP_ANONYMOUS标志(/dev/zero或{{ 3}}是POSIX)。

有趣的是,MAP_ANONYMOUS声称引入MAP_ANONYMOUS是为了消除创建匿名映射时打开/dev/zero的需要。

相关问题