17

Playing around with mmap for the fun of it, I have the following code:

(.. 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 ..)

This works as expected. But before I got to this, I tried...

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

... and mmap errored out with:

mmap: Permission denied

In general, what's the difference between the two flags (man page isn't to generous on this subject)? What sort of permission (and where) am I missing?

EDIT

Like it usually happens.. partially figured it out.

Turns out open needed an O_RDWR flag.

So, am I correct to assume that:

  • MAP_PRIVATE - changes are made in memory only, not saved to disk?
  • MAP_SHARED - changes would be saved to disk...

... but I'm not saving anything to disk anywhere, I thought? Just operating on memory.

2
  • 3
    , O_RDONLY); The file is read-only. It cannot be used as a backing storage for a PROT_READ|PROT_WRITE mmap()ed area because it is not writable. The MAP_PRIVATE mapping does not need to write to the file (the file is only used for reading, presumably by COW) Note: I would not expect tilde expansion to work for open(2). It would amaze me if it works. Commented Mar 1, 2012 at 16:12
  • Right, it was just a quick way to get the real base dir out of there, didn't even think about it. Thanks, fixed for the sake of correctness. Commented Mar 1, 2012 at 19:42

2 Answers 2

25

You opened the file in read-only mode. Then you attempted to mmap part of it in read/write mode with MAP_SHARED set. In this context, MAP_SHARED implies that if you write to the mmap'd region your changes will be committed back to the mapped file itself. You can't do this because you opened the file in read-only mode.

MAP_PRIVATE works because writes to the mmap'd region are not committed back to the original file. When you write to the region, the pages that were written to are copied to a different region of memory, possibly backed by swap space.

Sign up to request clarification or add additional context in comments.

Comments

10

Writes to a MAP_SHARED segment are carried through to the underlying file. You opened the file with O_RDONLY, which conflicts with the PROT_WRITE flag, thereby preventing MAP_SHARED from being able to write back to the file.

MAP_PRIVATE does not carry writes back to the underlying file, so the fact that you opened the file O_RDONLY is not an issue.

8 Comments

When are my changes in memory commited to disk? Do I need to call, or is it automatic? If so, any buffering?
Short anwer: you don't know. Anything between now and eternity. munmap() may flush the disk buffers, depending on the phase of the moon.
Got it. Also found msync, which promises to force a flush/sync. Thanks.
@wildplasser In my experience munmap() never flushes buffers. Thus you can use mmap/munmap to implement address space windowing when physical memory exceeds virtual memory address space.
That is correct. It just leaves them on the write queue (if they are dirty) MAP_SYNC will cause munmap() to block until they are actually written (just like msync()). That is the phase of the moon part of the story.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.