20

If I create an mmap(2) of a file with a prot parameter of PROT_READ only and the file backing it is also read-only and does not change, is there any performance difference (or any difference at all) between MAP_SHARED and MAP_PRIVATE ? Will the kernel do something differently between the two?

(The documentation only refers to difference of behaviour in terms of "updates", but as it is PROT_READ there can be no updates. I wonder if there is some other difference?)

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319

2 Answers2

4

Under MAP_PRIVATE, the Linux manpage says that it is unspecified whether changes made to the file after the mmap() call are visible in the mapped region. That is not the case with MAP_SHARED. So if you need the contents of the mapping to be updated together with the contents of the file, you had better use MAP_SHARED. If the underlying file itself is read-only and cannot change then of course none of this is applicable.

If PROT_READ is used, I can see nothing else that should be different between MAP_PRIVATE and MAP_SHARED. In fact, despite the above warning about unspecified behaviour, my guess (which I have not tested) would be that in practice there is no difference at all between the two under PROT_READ.

Celada
  • 21,627
  • 4
  • 64
  • 78
  • I've updated/clarified the question sorry. Assume the file is read only and the map is read only. There are no changes to the file and there are no changes to the memory region. Does the kernel do something differently between the two in this case? – Andrew Tomazos Jan 19 '13 at 23:28
  • I doubt very much that the kernel does anything differently between `MAP_SHARED` and `MAP_PRIVATE` in the case of a `PROT_READ` mapping for "normal", local filesystem types. But I believe Linux delegates actual implementation of `mmap()` to the filesystem, so to be absolutely sure, you'd have to audit the implementations of `mmap()` in all of the filesystem types that support it It's certainly plausible that, say for example, if you `mmap` a file over NFS, it caches the file's contents more aggressively if `MAP_PRIVATE` is used. I still say unlikely... but it's possible. – Celada Jan 19 '13 at 23:40
  • 2
    @Celada: The kernel sure does something different. `MAP_PRIVATE` is _private_, so logically data is loaded into a "secret" location (technically it's CoW). While one-way visibility (modifications of the mapping aren't seen in the file, but file modifications might be seen in the mapping) is possible, it's difficult and requires extra work. `MAP_SHARED` will simply give the same page from the buffer cache to anyone who maps it. Now in this case, two-way visibility is automatic (and thus guaranteed). You will see file changes in a private mapping if an unmodified page has been paged out... – Damon Apr 14 '14 at 09:47
  • 1
    ... and is subsequently reloaded from disk. But otherwise, you simply won't, since the OS would have to keep track of every private page anyone on the system has mapped, and reload them all every time, doing a lot of memory copying. It is **much** easier and more efficient (in particular for something few people, if any, ever need) to simply say it's undefined (which is basically a blanket permission for the OS to do whatever is the least work). – Damon Apr 14 '14 at 09:48
  • @Damon you're missing the point. The mapping has PROT_WRITE unset, so the CoW never happens – osvein May 25 '20 at 13:50
2

The mmap syscall eventually calls do_mmap_pgoff to setup to call mmap_region to do the actual work.

It passes through the flag VM_SHARED to indicate whether it is a shared or private mapping in vm_flags to mmap_region

In do_mmap_pgoff there is:

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;

    ...
    }

    ...
}

Which says if there is a file backing and the mapping is MAP_SHARED and the file is read-only then turn off the VM_SHARED shared flag.

However VM_MAYSHARE is still set so this can be used to change behaviour.

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • 1
    But it will still see the `VM_MAYSHARE` flag. I wonder if that could make a difference. I have no idea. – Celada Jan 20 '13 at 00:28
  • @Celada: Yes you are right, the `VM_MAYSHARE` flag is still set, and this is referenced from all over the place - so my reasoning is incorrect, I misread the code. – Andrew Tomazos Jan 20 '13 at 14:55