【问题标题】:What is the difference between MAP_SHARED and MAP_PRIVATE in the mmap function?mmap 函数中的 MAP_SHARED 和 MAP_PRIVATE 有什么区别?
【发布时间】:2012-03-01 16:07:53
【问题描述】:

为了好玩而玩弄mmap,我有以下代码:

(.. snip ..)
fd = open("/home/me/straight_a.txt", O_RDONLY);
if (fd == -1) {
    perror("open");
    exit(1);
}

m = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);

if (m == MAP_FAILED) {
    perror("mmap");
    exit(1);
}

printf("m is %p\n", m);

printf("*m = %c\n", *m);
printf("*(m+1) = %c\n", *(m+1));
(.. snip ..)

这按预期工作。但在此之前,我尝试过......

m = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0);

... 和 mmap 出错:

mmap: Permission denied

一般来说,这两个标志之间有什么区别(手册页在这个主题上不是很慷慨)?我缺少什么样的权限(以及在哪里)?

编辑

就像它通常发生的那样......部分弄清楚了。

原来open 需要一个O_RDWR 标志。

那么,我的假设是否正确:

  • MAP_PRIVATE - 更改仅在内存中进行,不保存到磁盘?
  • MAP_SHARED - 更改将保存到磁盘...

...但我没有在任何地方保存任何东西到磁盘,我想?只是在内存上操作。

【问题讨论】:

  • , O_RDONLY); 该文件是只读的。它不能用作PROT_READ|PROT_WRITE mmap()ed 区域的后备存储,因为它不可写。 MAP_PRIVATE 映射不需要写入文件(该文件仅用于读取,可能是由 COW 使用的) 注意:我不希望波浪号扩展适用于 open(2)。如果它有效,我会感到惊讶。
  • 对,这只是从那里获取真正的基本目录的快速方法,甚至没有考虑过。谢谢,为了正确起见已修复。

标签: c linux mmap


【解决方案1】:

您以只读模式打开文件。然后,您尝试在设置了 MAP_SHARED 的情况下以读/写模式映射其中的一部分。在这种情况下,MAP_SHARED 意味着如果您写入 mmap'd 区域,您的更改将被提交回映射文件本身。您不能这样做,因为您以只读模式打开了文件。

MAP_PRIVATE 有效,因为对 mmap 区域的写入不会提交回原始文件。当您写入该区域时,被写入的页面会被复制到不同的内存区域,可能由交换空间支持。

【讨论】:

    【解决方案2】:

    对 MAP_SHARED 段的写入会传递到底层文件。您使用 O_RDONLY 打开文件,这与 PROT_WRITE 标志冲突,从而阻止 MAP_SHARED 能够写回文件。

    MAP_PRIVATE 不会将写操作返回到底层文件,因此您打开文件 O_RDONLY 的事实不是问题。

    【讨论】:

    • 我的内存更改何时提交到磁盘?我需要打电话吗,还是自动的?如果是这样,任何缓冲?
    • 简短的回答:你不知道。从现在到永恒之间的任何事情。 munmap() 可能会刷新磁盘缓冲区,具体取决于月相。
    • 知道了。还发现了msync,它承诺强制刷新/同步。谢谢。
    • @wildplasser 根据我的经验, munmap() 从不刷新缓冲区。因此,当物理内存超过虚拟内存地址空间时,您可以使用 mmap/munmap 实现地址空间窗口化。
    • 没错。它只是将它们留在写入队列中(如果它们是脏的) MAP_SYNC 将导致 munmap() 阻塞,直到它们被实际写入(就像 msync() 一样)。这就是故事的月相部分。
    猜你喜欢
    • 2016-01-07
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2016-12-21
    • 2015-08-09
    • 2019-01-25
    • 1970-01-01
    • 2020-11-27
    相关资源
    最近更新 更多