39

A fork() system call clones a child process from the running process. The two processes are identical except for their PID.

Naturally, if the processes are just reading from their heaps rather than writing to it, copying the heap would be a huge waste of memory.

Is the entire process heap copied? Is it optimized in a way that only writing triggers a heap copy?

3 Answers 3

34

The Linux kernel does implement Copy-on-Write when fork() is called. When the syscall is executed, the pages that the parent and child share are marked read-only.

If a write is performed on the read-only page, it is then copied, as the memory is no longer identical between the two processes. Therefore, if only read-operations are being performed, the pages will not be copied at all.

6
  • 1
    +1 Thanks! 1. Could you please provide reference links? 2. Is the heap copied entirely, or in parts?
    – Adam Matan
    Aug 20, 2014 at 15:19
  • 4
    2. - In pages :) The kernel has very little understanding of what "heap" is - for the kernel, it's just a bunch of mmapped private pages, that the libc allocators handle as it please.
    – qdot
    Aug 20, 2014 at 15:21
  • Is this really a fork-bomb necessarily? It seems to me that rather than forking the current process, this code will create more instances of the same program that execute from start rather than from the next instruction after the fork() call.
    – sherrellbc
    Oct 20, 2014 at 12:55
  • @mmk FYI, I was quite surprised by your "Interesting side-note:" and so I tested (on Linux 3.2.0) to see, and it does not appear to be true. I used /proc/self/pagemap to determine the virtual address to physical page mapping for the purposed of the test. As I expected, if the grand-child and only the grand-child writes the shared page, then the parent and original child continue to share it. Only the grand-child ends up with a private copy.
    – Celada
    Nov 13, 2014 at 17:41
  • @Celada. Hmm. I had read this somewhere, and I don't remember the kernel version it was referring to (probably an older one?), so, it may no longer be valid.
    – mmk
    Nov 14, 2014 at 1:23
28

The entirety of fork() is implemented using mmap / copy on write.

This not only affects the heap, but also shared libraries, stack, BSS areas.

Which, incidentally, means that fork is a extremely lightweight operation, until the resulting 2 processes (parent and child) actually start writing to memory ranges. This feature is a major contributor to the lethality of fork-bombs - you end up with way too many processes before kernel gets overloaded with page replication and differentiation.

You'll be hard-pressed to find in a modern OS an example of an operation where kernel performs a hard copy (device drivers being the exception) - it's just far, far easier and more efficient to employ VM functionality.

Even execve() is essentially "please mmap the binary / ld.so / whatnot, followed by execute" - and the VM handles the actual loading of the process to RAM and execution. Local uninitialized variables end up being mmaped from a 'zero-page' - special read-only copy-on-write page containing zeroes, local initialized variables end up being mmaped (copy-on-write, again) from the binary file itself, etc.

3
  • 1
    One notable exception is Java processes. Search for "fork java memory" and you will find dozens of issues affecting large server JVM or embedded JVM trying to execute a small shell command and miserably crashing on a "Cannot allocate memory" exception (these are just random links, this issue is systemic to the Java environments). This SO answer accuses the JVM's garbage collector & JIT compiler from keeping processes memory from being shared. Mar 2, 2017 at 13:12
  • 1
    Although this is absolutely correct, it may be useful to note that fork() used to copy the entire thing, so it wasn't always as lightweight as it is now. That's the reason for the existence of the vfork() system call which, nowadays, is largely useless and the speedup it provides is negligible.
    – forest
    Nov 20, 2021 at 0:36
  • @WhiteWinterWolf Wouldn’t shelling out immediately exec after the fork, thus not giving time to the garbage collector to dirty the memory pages?
    – HappyFace
    Apr 24, 2022 at 19:13
13

Linux does Copy-on-Write. As fork creates a new process, the allocated pages are marked as readonly and shared between the parent and child. When either of them tries to modify a page, a page fault is generated resulting in copying the page and adjusting the page table appropriately.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.