在Linux中,mmap(2)手册页介绍了匿名映射
。。。没有任何文件支持;其内容初始化为零。
FreeBSD mmap(2)手册页没有对零填充进行类似的保证,尽管它确实承诺非匿名映射中文件末尾的字节将被零填充。
哪种类型的Unix承诺从匿名mmap返回零初始化的内存?在实践中,哪一个返回零初始化内存,但在其手册页中没有做出这样的承诺?
我的印象是零填充部分是出于安全原因。我想知道是否有任何mmap实现会跳过被映射,屏蔽,然后被单个进程再次映射的页面的零填充,或者是否有任何实现使用伪随机位或一些非零常量填充新映射的页面。
PS显然,甚至brk和sbrk都用于保证零填充页面。我在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]);
}
很难说是哪个承诺了什么而没有简单地详尽列举所有手册页或其他发行文档,但是处理的底层代码MAP_ANON
(通常?总是?)也用于映射bss空间中的可执行文件,并且bss空间需要为零。 -填充。因此,这很有可能。
至于如果取消映射和重新映射,则“退还你的旧值”(或一些非零值,但很可能是你的旧值),如果某些系统对释放分配“偷懒”,则肯定是可行的。我只使用了少数几个mmap
首先支持的系统(BSD和Linux派生),但没有一个是那种懒惰的,至少在内核代码处理中没有mmap
。
sbrk
填充“重新生成”页面的原因可能为零,也可能不为零,这可能与历史记录有关,也可能与历史记录无关。与我从旧的,预调出当前FreeBSD的代码相匹配mmap
天:有两个半秘密变量,minbrk
和curbrk
,都brk
和sbrk
只会调用SYS_break
(真正的系统调用),如果他们正在curbrk
向至少一个值minbrk
。(实际上,这看起来有点破损:brk
至少具有这种行为,但sbrk
仅将其参数添加到curbrk
并调用SYS_break
。由于内核将in sys_obreak()
in检入/sys/vm/vm_unix.c
,因此似乎是无害的,因此太负的操作sbrk()
将失败EINVAL
。)
我必须查看Linux C库(然后可能还要查看内核代码),但是它可能只是忽略了“降低中断”的尝试,而只是在libc中记录了“逻辑中断”值。如果你有mmap()
没有向后兼容性的要求,可以实现brk()
和sbrk()
完全libc中,使用匿名映射,这将是微不足道两者实施的“增长-仅”,因为它是。
我一直不知道,直到我查了一下,但是MAP_ANON不在POSIX中。
@Olsonist:这有点令人惊讶,但是它增加了“关于MAP_ANON的坚决承诺”,甚至没有保证MAP_ANON将会存在。:-)