【问题标题】:why we can mmap to a file but exceed the file size?为什么我们可以映射到文件但超出文件大小?
【发布时间】:2018-05-16 05:03:26
【问题描述】:

例如。

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);

请注意,我在此处映射了 + 10。 但它仍然有效?

为什么系统不应用任何检查? 危险吗?

谢谢

【问题讨论】:

  • 编辑标签。 cc++ 都具有误导性
  • 为什么应该这样?
  • @coderredoc mmap() 可以从 c 和 c++ 中很好地调用。
  • @JeremyFriesner.: 是的..但我不确定使用::?这就是为什么说。

标签: c++ linux system-calls mmap


【解决方案1】:

mmap 的签名是:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

引用 Michael Kerrisk 的话:

length 参数指定映射的大小(以字节为单位)。 虽然长度不需要是系统页面大小的倍数 (由 sysconf(_SC_PAGESIZE) 返回),内核在 这个大小的单位,所以长度实际上是向上取整到 页面大小的下一个倍数。 - Linux 编程接口(第 49 章)

引用罗伯特·洛夫的话:

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

【讨论】:

  • 这表明 mmap 内存总是可以大于请求的。但是 OP 的问题是如果 mmap 内存严格大于备份它的文件会发生什么,例如,超出文件大小的内存访问会产生故障吗?它会默默地将文件扩展零吗?等等。
  • 问题是询问更多类似的问题:假设我们 mmap() 一个大小 = 10Kbyte 的空文件,并写入偏移量 9K。会保存到文件中吗?
【解决方案2】:

我假设您的系统正在运行 Linux。请务必阅读intro(2)

我们可以mmap(2) 文件超过它们的大小,因为如果我们不能,只有页面大小的精确倍数(通常是 4Kbytes,也许是 1Mbytes,参见sysconf(3)PAGESIZE)可以进行内存映射。如果是这种情况,内存映射文件的用处就会小得多。此外,mmap-ed 文件的大小会随时间而变化(其他进程 write(2)-ing 并附加到它,调用 ftruncate(2),等等......)所以它对 kernel 没有意义要求(或强制)它不改变。

仔细阅读mmap(2)的文档,上面写着:

文件以页面大小的倍数进行映射。对于一个文件 不是页面大小的倍数,剩余内存清零时 映射,并且对该区域的写入不会写入文件。

(所以内核当然会做一些检查,可能比你想象的要多得多)

mmap 可能会失败,因此您的代码应该检查它,例如跟随它:

 if ((void*)addr == MAP_FAILED) 
      { perror("mmap"); exit(EXIT_FAILURE); };

顺便说一句,您的问题不是 C++ 特定的,而是 POSIX 或 Linux 特定的(其他操作系统可能不提供 memory mapped files,或者可能对它们施加其他限制)。

请注意,内存映射非常常见。它被mmap 使用,也被execve(2) 使用。您可以通过using /proc/ 了解一些给定的processvirtual address space(请参阅proc(5) 并在您的终端中尝试cat /proc/self/mapscat /proc/$$/maps)。 mmap 经常被使用:malloc(3)operator newdlopen(3)ld-linux(8),用于动态链接的共享库。

还可以阅读一些关于 Linux 或 POSIX 编程的书籍(例如旧的 Advanced Linux Programming,可免费下载或更新的东西)和 Operating Systems: Three Easy Pieces

【讨论】:

    猜你喜欢
    • 2020-03-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 2012-12-24
    相关资源
    最近更新 更多