为什么我们可以映射到文件但超出文件大小?

cha*_* jc 6 c++ linux mmap system-calls

例如。

fd = ::open ("/test.txt", O_RDONLY, 0);
struct stat buf;
fstat(fd, &buf);
char* addr = (char*)::mmap(NULL, buf.st_size + 10, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0);
Run Code Online (Sandbox Code Playgroud)

请注意,我在这里映射了+ 10。但它仍然有效吗?

为什么系统不进行任何检查?危险吗?

谢谢

nac*_*ulk 9

mmap 的签名是:

\n\n
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);\n
Run Code Online (Sandbox Code Playgroud)\n\n

引用迈克尔·克里克的话:

\n\n
\n

length 参数指定映射的大小(以字节为单位)。\n 尽管 length 不需要是系统页面大小的倍数\n(由 sysconf(_SC_PAGESIZE) 返回),但内核会在\n 此大小的单位,因此长度实际上向上舍入到\n 页面大小的下一个倍数。\n - Linux 编程接口(第 49 章)

\n
\n\n

引用罗伯特·洛夫的话:

\n\n
\n

mmap() 系统调用在页面上运行。addr 和 offset 参数都必须在页大小边界上对齐。也就是说,它们必须是页面大小的整数倍。因此,映射是页面的整数倍。如果调用者提供的 len 参数未在页面边界上对齐\xe2\x80\x94,可能是因为底层文件\xe2\x80\x99s 大小不是页面大小的倍数\xe2\x80\x94,则映射将向上舍入到下一个整页。添加的内存中的最后一个有效字节和映射末尾之间的字节均用零填充。从该区域读取的任何内容都将返回零。对该内存的任何写入都不会影响备份文件,即使它被映射为 MAP_SHARED。仅原始 len 字节被写回文件。\n - Linux 系统编程(第 4 章)

\n
\n

  • 这表明 mmap 内存总是可以大于请求的内存。但OP的问题是如果mmap内存严格大于备份它的文件会发生什么,例如,超出文件大小的内存访问会产生错误吗?它会默默地将文件扩展为零吗?ETC。 (4认同)
  • 问题是问更多类似的问题:想象我们 mmap() 一个大小 = 10Kbyte 的空文件,并写入偏移量 9K。这会保存到文件中吗? (4认同)