Is this a safe way to share read-only memory with child processes?
I want to allocate and initialise a fairly large chunk of contiguous memory (~1GB), then mark it as read-only and fork multiple (say several dozen) child processes which will use it, without making their own copies of the memory (the machine won't have enough memory for this).
Am I right in thinki开发者_如何学Cng that if I malloc
the memory as usual, then mark it as read-only with mprotect(addr, size, PROT_READ)
and then fork
, this will allow the child processes to safely use the memory without causing it to be copied? (Providing I ensure nothing tries to write to the allocated memory after the mprotect
call).
edit: Thanks for all the answers.
A followup question - I was planning on using shmget
, but I thought it used mm
and thus would be limited to smaller allocations (see the Restrictions section of this page). eg /proc/sys/kernel/shmmax
is 32MB on the server I'm using this one. But I want 1GB of contiguous memory. Am I wrong about this limitation?
man mprotect
The implementation will require that addr be a multiple of the page size as returned by sysconf().
The behaviour of this function is unspecified if the mapping was not established by a call to mmap().
mprotect
only works on pages, not arbitrary byte ranges, so in generalmalloc
is inappropriate.posix_memalign
may help, but...- While it may work on your system at the present time, you shoud not
mprotect
anything that you didn'tmmap
yourself. Usemmap(0, pages*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)
instead.
You are not right by the reason than any of child processes can call mprotect()
to remove protection and start writing there. If the pages have not been copied, it would violate the principles of fork()
.
Even if it works that way that copy-on-write is used for forked processes, I don't reckon any place in standards that says so (POSIX doesn't say it's copy-on-write, for instance).
Instead of using non-standard behavior, you may use standard measures to share memory. For example, the POSIX shared memory with shm_open
and consequent mmap
(as was pointed out in comment and explained in his post by ephemient). The file descriptor will be preserved through forking.
There is no need to mark it read-only, just get your child processes to leave it alone.
If neither the parent nor child writes to it, it should remain shared. If you don't ever want to change it, that's fine.
If you want to write to it, you'll want to use mmap with MAP_SHARED.
You are making an assumption that the kernel would do copy-on-write optimization and not copy the mprotect
-ed pages. I would'n count on it though. malloc
-ed memory has all sorts of metadata floating around it - guard pages, etc. etc. and only Ulrich Drepper knows what's going on inside libc :)
It would probably be easier and safer to prepare data in a disk file and them mmap
it into all the processes, or just go normal POSIX shm_open
route.
My understanding is yes, since Linux uses a copy-on-write mechanism for memory pages passed to a child process.
You could do it that way.
An alternative is to use mmap().
Another alternative is to use the POSIX shared memory (shm_open()); the other main alternative is System V shared memory (shmget(), shmat()). One advantage of the formal shared memory systems is that your parent process can create the memory and then unrelated process could connect to it - if that was beneficial.
精彩评论