为什么以下代码正常运行?
void continuous_mmap (void)
{
struct stat buf;
int fd = open("file_one", O_RDONLY), i;
char *contents;
fstat(fd, &buf);
contents = mmap(NULL, buf.st_size, PROT_WRITE, MAP_PRIVATE, fd, 0);
close (fd);
mprotect(contents, buf.st_size, PROT_READ);
for (i = 0; i < 15; i++) {
printf ("%s\n", contents);
sleep (1);
}
munmap(contents, buf.st_size);
}
首先,文件保持同步(编辑和保存文件外部自动打印更新的内容),即使附加到。如果没有segfaulting,我的代码如何能够超出我映射的字节数(初始文件大小)?是因为mmap
总是将长度向上舍入到系统页面大小?如果是这样,这种行为一般可以依赖于POSIX
系统(我在mmap
手册页中找不到任何此类要求。)
其次,文本如何自动附加'0'
?是因为非映射字节会自动归零吗?这种行为可以依赖吗?
答案 0 :(得分:2)
是标准说
系统应始终零填充任何 对象末尾的部分页面。 此外,系统永远不会写 删除最后一个的任何修改部分 一个超出它的对象的页面 端。
您不应该使用mmap
来电的此功能,但ftruncate
可以根据您的需要延长文件。
答案 1 :(得分:1)
POSIX甚至不会要求一个非常重要的页面大小;理论上,实现可以具有1字节的“页面”大小。类似地,似乎没有指定从文件大小超过页面的其余部分读取零。我可以想象一些破坏的实现泄漏了在这里被截断的旧文件内容,但我认为这是一个重大的安全/隐私泄露,会使这种实现在现实世界中无关紧要。当然,他们可以用0xDEADBEEF
填补空间,然后你就会失去运气。
即使您可以假设零填充(大多数实际操作系统可能就是这种情况),我会提醒您不要使用它。如果您的文件恰好是系统页面大小的两倍,会发生什么?突然间,您的代码在读取结束时崩溃,或者(可能更糟)从不相关的页面读取,这些页面恰好被映射到文件的映射旁边。这是一个非常非常讨厌的错误,你可能无法捕获,因为文本文件是系统页面大小的精确倍数的可能性非常低。
答案 2 :(得分:0)
您看到文件的外部更新的原因,即使它已映射MAP_PRIVATE
,是因为您尚未写入映射,因此系统未向您提供该文件的私有副本页面呢。允许此行为,但不是必需的。
如果你的应用程序在循环之前修改了contents[0]
,它将不看到外部变化。