【问题标题】:Is there a difference between mmap MAP_SHARED and MAP_PRIVATE when PROT_READ is also used?当还使用 PROT_READ 时,mmap MAP_SHARED 和 MAP_PRIVATE 之间有区别吗?
【发布时间】:2013-01-19 23:16:57
【问题描述】:

如果我创建一个 prot 参数为 PROT_READ 的文件的 mmap(2) 并且支持它的文件也是只读的并且不会更改,是否存在任何性能差异(或根本差异) 在MAP_SHAREDMAP_PRIVATE 之间?内核会在两者之间做一些不同的事情吗?

(文档仅提及“更新”方面的行为差异,但因为它是PROT_READ,所以无法更新。不知道是否还有其他差异?)

【问题讨论】:

    标签: c linux linux-kernel mmap


    【解决方案1】:

    MAP_PRIVATE 下,Linux 联机帮助页表示未指定在 mmap() 调用后对文件所做的更改是否在映射区域中可见。 MAP_SHARED 并非如此。所以如果你需要映射的内容和文件的内容一起更新,你最好使用MAP_SHARED。如果底层文件本身是只读的并且无法更改,那么这当然不适用。

    如果使用PROT_READ,我看不出MAP_PRIVATEMAP_SHARED 之间应该有什么不同。事实上,尽管有上述关于未指定行为的警告,但我的猜测(我没有测试过)是,在实践中,PROT_READ 下的两者之间根本没有区别。

    【讨论】:

    • 对不起,我已经更新/澄清了这个问题。假设文件是​​只读的,而地图是只读的。文件没有变化,内存区域也没有变化。在这种情况下,内核会在两者之间做些什么不同的事情吗?
    • 我非常怀疑内核在 MAP_SHAREDMAP_PRIVATE 之间做的任何不同的事情在 PROT_READ 映射的情况下“正常”,本地文件系统类型。但我相信 Linux 将 mmap() 的实际实现委托给文件系统,因此绝对可以肯定,您必须在所有支持它的文件系统类型中审核 mmap() 的实现。这当然是合理的,例如,如果您通过 NFS mmap 一个文件,如果使用 MAP_PRIVATE,它会更积极地缓存文件的内容。我仍然说不太可能……但有可能。
    • @Celada:内核确实做了一些不同的事情。 MAP_PRIVATEprivate,所以逻辑上数据被加载到一个“秘密”位置(技术上它是 CoW)。虽然单向可见性(在文件中看不到映射的修改,但在映射中可能会看到文件修改)是可能的,但这很困难并且需要额外的工作。 MAP_SHARED 只会将缓冲区缓存中的相同页面提供给映射它的任何人。现在在这种情况下,双向可见性是自动的(因此得到保证)。如果未修改的页面已被调出,您将在私有映射中看到文件更改...
    • ... 并随后从磁盘重新加载。但是否则,您根本不会,因为操作系统必须跟踪系统上任何人映射的每个私有页面,并且每次都重新加载它们,进行大量内存复制。简单地说它是未定义的(这基本上是操作系统做任何最少工作的一揽子许可)更容易和更有效(特别是对于很少有人需要的东西,如果有的话) )。
    • @Damon 你没抓住重点。映射未设置 PROT_WRITE,因此 CoW 永远不会发生
    【解决方案2】:

    mmap 系统调用最终调用do_mmap_pgoff 来设置调用mmap_region 来完成实际工作。

    它通过标志VM_SHARED来指示它是vm_flagsmmap_region中的共享还是私有映射

    do_mmap_pgoff 中有:

    if (file)
    {
        switch (flags & MAP_TYPE)
        {
        case MAP_SHARED:
    
            if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE))
                return -EACCES; /* error */
    
            ...
    
            vm_flags |= VM_SHARED | VM_MAYSHARE;
            if (!(file->f_mode & FMODE_WRITE))
                vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
    
            /* fall through */
        case MAP_PRIVATE:
    
                ...
    
        break;
    
        ...
        }
    
        ...
    }
    

    如果有文件支持并且映射为MAP_SHARED 并且文件是只读的,则关闭VM_SHARED 共享标志。

    但是VM_MAYSHARE 仍然设置,因此可以用来改变行为。

    【讨论】:

    • 但它仍然会看到VM_MAYSHARE 标志。我想知道这是否会有所作为。我不知道。
    • @Celada:是的,你是对的,VM_MAYSHARE 标志仍然设置,而且到处都引用了它 - 所以我的推理不正确,我误读了代码。
    猜你喜欢
    • 2016-01-07
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2011-04-10
    • 2012-01-22
    • 2012-02-16
    • 2012-12-17
    • 1970-01-01
    相关资源
    最近更新 更多