Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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?

like image 984
John Carter Avatar asked Feb 09 '10 19:02

John Carter


3 Answers

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

  1. mprotect only works on pages, not arbitrary byte ranges, so in general malloc is inappropriate. posix_memalign may help, but...
  2. While it may work on your system at the present time, you shoud not 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.
like image 67
ephemient Avatar answered Sep 28 '22 07:09

ephemient


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.

like image 31
P Shved Avatar answered Sep 28 '22 09:09

P Shved


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.

like image 20
MarkR Avatar answered Sep 28 '22 09:09

MarkR