Nei sistemi moderni nessuna memoria viene effettivamente copiata solo perché viene utilizzata una chiamata di sistema fork. È tutto contrassegnato come sola lettura nella tabella delle pagine in modo tale che al primo tentativo di scrivere una trappola nel codice del kernel accadrà. Solo una volta che il primo processo tenterà di scrivere, la copia avverrà.
Questo è noto come copy-on-write.
Tuttavia potrebbe essere necessario tenere traccia anche dello spazio degli indirizzi impegnato. Se non è disponibile memoria o swap nel momento in cui il kernel deve copiare una pagina, deve terminare qualche processo per liberare memoria. Questo non è sempre desiderabile, quindi è possibile tenere traccia di quanta memoria è impegnata il kernel.
Se il kernel si impegna a più della memoria disponibile + swap, può dare un codice di errore al tentativo di chiamare fork. Se è disponibile una quantità sufficiente, il kernel eseguirà il commit per l'intera dimensione virtuale del genitore per entrambi i processi dopo il fork.
Non preoccuparti, fa una copia pigra (copia su scrittura). Gli indirizzi di memoria virtuale di entrambi i processi puntano inizialmente alle stesse pagine, ma quando il processo fork tenta di modificarlo, crea effettivamente una copia fisica della pagina (da quel momento in poi, quella pagina risiede in due punti nella RAM).
Attenzione, nessuno dei footprint di memoria segnalati in realtà ti dice quanta RAM sta utilizzando il processo. A causa dello scambio, della condivisione della memoria e di altri problemi con la memoria virtuale, è impossibile saperlo con certezza. Alcune parti dello spazio di memoria sono librerie condivise (dove contarle?), alcune si riferiscono a memoria non RAM (altri dispositivi hardware), alcune sono attualmente sostituite, altre non sono ancora state copiate (copia su scrittura) e presto. Leggi questo:
https://lwn.net/Articles/642202/
C'è l'impostazione del kernel
/proc/sys/vm/overcommit_memory
Citazione dall'eccellente articolo:
Since 2.5.30 the values are: 0 (default): as before: guess about how much
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise
about the overcommit - never commit a virtual address space larger than swap
space plus a fraction overcommit_ratio of the physical memory. Here
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable
parameter. It is possible to set overcommit_ratio to values larger than 100.
(See also Documentation/vm/overcommit-accounting.)
Questo vale sia per le forcelle che per il normale malloc. Cioè. se lo imposti su 0, fork verrà copiato su write. Copia su scrittura significa che una volta che l'app è stata biforcata, entrambe le copie condivideranno le pagine di memoria util figlio o l'originale inizia a modificare la memoria.
Nella maggior parte delle distribuzioni so che l'overcommit è 0. Ma se lo imposti su 2, tutte le pagine di memoria saranno completamente supportate dalla memoria reale e in alcuni casi sotto un'elevata pressione della memoria saranno più stabili, ma alcuni programmi (ho affrontato gitk) che si basano sugli overcommit fallirà.