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 thinking 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 general malloc
is inappropriate. posix_memalign
may help, but...mprotect
anything that you didn't mmap
yourself. Use mmap(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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With