jba*_*ple 9 memory freebsd mmap
在Linux中,mmap(2)手册页解释了匿名映射
...没有任何文件支持; 其内容初始化为零.
FreeBSD mmap(2)手册页没有对零填充做出类似的保证,尽管它确实保证非匿名映射中文件结尾后的字节为零填充.
哪种口味的Unix承诺从匿名mmaps返回零初始化内存?哪些在实践中返回零初始化内存,但在他们的手册页上没有做出这样的承诺?
我的印象是零填充部分是出于安全原因.我想知道是否有任何mmap实现跳过零填充为mmapped,munmap,然后由单个进程再次mmapped的页面,或者如果任何实现用伪随机位或一些非零常量填充新映射的页面.
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]);
}
Run Code Online (Sandbox Code Playgroud)
Ral*_*phS 14
哪些 Unix 版本承诺从匿名 mmap 返回零初始化内存?
正如您在问题中所说,Linux 版本的 mmap承诺对匿名映射进行零填充:
MAP_ANONYMOUS该映射不受任何文件支持;其内容被初始化为零。
NetBSD版本的 mmap承诺对匿名映射进行零填充:
MAP_ANON映射不与任何特定文件关联的匿名内存。文件描述符不用于创建
MAP_ANON区域,并且必须指定为-1. 映射的内存将被零填充。
mmap 的 OpenBSD 联机帮助页不承诺对匿名映射进行零填充。然而,Theo de Raadt(著名 OpenBSD 开发人员)于2019 年 11 月在 OpenBSD 邮件列表上声明:
当然是用零填充的。还会是什么?没有其他可行的选择。
我认为说如此明显的话会损害信息的其余部分。
其他 OpenBSD 开发人员也没有反驳他。
AIX版本的 mmap承诺对匿名映射进行零填充:
MAP_ANONYMOUS指定创建一个新的、初始化为全零的匿名内存区域。
根据 nixdoc.net,HP-UX 版本的 mmap承诺对匿名映射进行零填充:
如果
MAP_ANONYMOUS在 中设置flags,则创建一个新的内存区域并将其初始化为全零。
Solaris版本的 mmap承诺对匿名映射进行零填充:
当
MAP_ANON在 中设置flags和fildes设置为 -1 时,mmap()提供将匿名页面返回给调用者的直接路径。此操作相当于传递mmap()一个打开的文件描述符/dev/zero并MAP_ANON从参数中删除flags。
此 Solaris 手册页为我们提供了一种获取零填充内存页的方法,而不依赖于与该标志一起使用的 mmap 的行为MAP_ANONYMOUS:不使用该MAP_ANONYMOUS标志,并创建由文件支持的映射/dev/zero。了解提供该文件的类 Unix 操作系统的列表会很有用/dev/zero,看看这种方法是否比使用MAP_ANONYMOUS标志更可移植(/dev/zero和MAP_ANONYMOUS都不是 POSIX)。
有趣的是,维基百科关于 /dev/zero 的文章声称引入该文章是为了消除创建匿名映射时MAP_ANONYMOUS打开的需要。/dev/zero
如果不简单地详尽列举所有手册页或其他发布文档,很难说哪些承诺是什么,但处理的底层代码MAP_ANON(通常?总是?)也用于在bss空间中映射可执行文件,并且bss空间需要为零-填充.所以这很可能.
至于"给你回旧的价值"(或者一些非零值,但很可能是你的旧值),如果你取消映射并重新映射,如果某些系统对于解除分配是"懒惰的",这似乎是可能的.我只使用了一些mmap首先支持的系统(BSD和Linux衍生产品),而且这两种方式都不是懒惰的,至少在内核代码处理方面是这样mmap.
究其原因sbrk可能是也可能不是零一补"再成长"页面可能依赖于历史,或缺乏.目前FreeBSD的代码我从老了,回想前匹配mmap天:有两个半秘密变量,minbrk和curbrk,都brk和sbrk只会调用SYS_break(真正的系统调用),如果他们正在curbrk向至少一个值minbrk.(实际上,这看起来略微沙哑的:brk有在,至少行为,但sbrk只是增加了它的参数curbrk,并调用SYS_break似乎因为内核检查是无害的,在,sys_obreak()在/sys/vm/vm_unix.c,所以太消极sbrk()将会失败EINVAL.)
我必须查看Linux C库(然后也可能是内核代码),但它可能只是忽略了"降低中断"的尝试,而只是在libc中记录"逻辑中断"值.如果您有mmap()并且没有向后兼容性要求,那么您可以使用匿名映射实现brk()并sbrk()完全在libc中实现,并且将它们实现为"仅增长"实际上是微不足道的.
| 归档时间: |
|
| 查看次数: |
4925 次 |
| 最近记录: |