What is the difference between calling mmap() on a

2020-04-10 01:18发布

问题:

I've been working on understanding how mmap() works with disk-backed files, and am mostly getting it, but I still have this question.

In a situation with a master process that forks a bunch of worker child processes, and a file-backed read-only mmapped db, does it matter if the mmaps happen in the master process before the forks, or in the child processes?

My understanding is that if it happens in the master process before the fork, then in the memory page table, all of the mapped pages are given the setting to make a page fault when they are read, triggering the kernel to load the page from disk (or from the page cache), and after the fork one child's reading of a page will mean the page is there in the mmap ready for other children to read without causing a major page fault.

But if the mmap happens in the child processes after the fork, do the other worker children get the benefit of sharing those loaded pages--are they all in effect using the same underlying mmap? Or does each worker child have to trigger a page fault and load each page themselves?

回答1:

It makes no difference to page fault activity. The page map of a file is global to the OS, it says whether a particular page is in RAM or not. The PTE of every process that has the file mapped points to this common data structure. There will only be a page fault for the first process that tries to access a page that isn't in RAM. That will trigger it to be read in, and other processes that try to access the same page will be able to use that RAM.

One difference between the two scenarios is whether the virtual addresses assigned to the mapped block are the same. If you call mmap before forking, the address will be copied in all the children. If you call mmap after forking, they could get different addresses. Using the same address in all processes allows you to pass pointers into the mapped block between the processes if you want. You can have pointers between objects within the block. If they're not all at the same address, you need to use offsets, and the processes will all have to add the offsets to the base address.