In che modo copy-on-write in fork () gestisce più fork?


23

Secondo Wikipedia (che potrebbe essere sbagliato)

Quando viene emessa una chiamata di sistema fork (), viene creata una copia di tutte le pagine corrispondenti al processo padre, caricata in una posizione di memoria separata dal sistema operativo per il processo figlio. Ma questo non è necessario in alcuni casi. Considerare il caso in cui un figlio esegue una " exec" chiamata di sistema (che viene utilizzata per eseguire qualsiasi file eseguibile dall'interno di un programma C) o esce molto presto dopo il fork(). Quando il figlio è necessario solo per eseguire un comando per il processo padre, non è necessario copiare le pagine del processo padre, poiché execsostituisce lo spazio degli indirizzi del processo che lo ha invocato con il comando da eseguire.

In tali casi, viene utilizzata una tecnica chiamata copia-su-scrittura (COW). Con questa tecnica, quando si verifica un fork, le pagine del processo padre non vengono copiate per il processo figlio. Invece, le pagine sono condivise tra il processo figlio e il processo padre. Ogni volta che un processo (padre o figlio) modifica una pagina, viene creata una copia separata di quella pagina specifica per quel processo (padre o figlio) che ha eseguito la modifica. Questo processo utilizzerà quindi la pagina appena copiata anziché quella condivisa in tutti i riferimenti futuri. L'altro processo (quello che non ha modificato la pagina condivisa) continua a utilizzare la copia originale della pagina (che ora non è più condivisa). Questa tecnica è chiamata copia su scrittura poiché la pagina viene copiata quando un processo scrive su di essa.

Sembra che quando uno dei processi tenta di scrivere sulla pagina una nuova copia della pagina viene allocata e assegnata al processo che ha generato l'errore di pagina. La pagina originale viene contrassegnata in seguito scrivibile.

La mia domanda è: cosa succede se fork()viene chiamato più volte prima che qualcuno dei processi abbia tentato di scrivere su una pagina condivisa?


Wikipedia ha ragione in questo caso, solo di più alto livello.
Didi Kohen,

1
Sì, copia su scrittura è una copia lenta, processo figlio copia la pagina quando prova a scriverla. Quindi sostanzialmente, dopo un fork, la memoria di quasi un bambino viene condivisa con il genitore. Tuttavia, prima di qualsiasi processo eseguito, ogni processo figlio ha ancora della memoria privata, modificata dalla nuova allocazione dei genitori. Ciò significa che anche senza alcuna azione il processo figlio biforcuto ha un po 'di memoria privata. Possiamo verificarlo con pmap -XX PIDo cat /proc/PID/smap.
dove23 del

Riguardo a "La pagina originale viene contrassegnata in seguito scrivibile.", Chi sarà la proprietaria? Qui l'altro processo che non ha provato a scriverlo?
Adil,

È adorabile. Cominciamo a insegnare questo nelle scuole materne
ed22,

Risposte:


18

Non succede nulla di particolare. Tutti i processi condividono lo stesso insieme di pagine e ognuno ottiene la propria copia privata quando desidera modificare una pagina.


Destra. Il punto è che è il processo figlio che è speciale, che ha il compito di copiare se tenta di scrivere sulla pagina condivisa. Né il genitore né gli altri bambini devono conoscere la modifica se viene eseguita correttamente.
Charles Stewart,

9
Il processo figlio non è così speciale. Entrambi i processi figlio e padre hanno lo stesso set di pagine di sola lettura dopo il fork. Per quanto riguarda queste pagine, la gestione delle pagine è simmetrica.
jlliagre,

3

Il comportamento di fork () dipende dal fatto che il sistema * nix abbia o meno una MMU. Su un sistema non MMU (come i primi PDP-11) la chiamata di sistema fork () ha copiato tutta la memoria del genitore per ciascun figlio. Su un sistema * nix basato su MMU, il kernel contrassegna tutte le pagine non stack come R / O e le condivide tra padre e figlio. Quindi quando uno dei processi scrive su una pagina qualsiasi, la MMU intrappola il tentativo, il kernel alloca una pagina scrivibile e aggiorna le tabelle delle pagine MMU in modo che puntino alla pagina ora scrivibile. Questo comportamento Copy-on-Write fornisce una maggiore velocità poiché inizialmente è necessario allocare e clonare solo uno stack privato per ciascun processo figlio.

Se si esegue un codice padre tra ciascuna chiamata fork (), i processi figlio risultanti differiranno per le pagine che sono state modificate dal padre. D'altra parte, se il genitore emette semplicemente più chiamate fork (), ad esempio in un ciclo, i processi figlio saranno quasi identici. Se viene utilizzata una variabile di loop locale, questa sarà diversa all'interno dello stack di ogni bambino.


0

Quando il sistema preforma un fork, di solito (ciò può dipendere dall'implementazione), contrassegna anche le pagine come di sola lettura e contrassegna il processo padre come master di queste pagine.
Quando si tenta di scrivere su queste pagine, si verifica un errore di pagina e il sistema operativo subentra, copiando l'intero elenco di pagine o solo quelle modificate (di nuovo, a seconda dell'implementazione), quindi il processo di scrittura avrà una copia scrivibile.
Quando ci sono più processi biforcati dallo stesso, quando il processo "master" scrive nella sua memoria, gli altri processi ottengono le loro pagine equivalenti copiate.


quale sistema fa questo? Linux usa un'implementazione copy-on-write
brauliobo

Ecco come funziona il copy-on-write ...
Didi Kohen,

3
@DavidKohen non è così che funziona il copy-on-write in nessuna versione di cui abbia mai sentito parlare. Non esiste un processo "master". Se un singolo processo scrive le pagine condivise, la sua copia viene assegnata a una privata mentre tutti gli altri processi continuano a condividerla.
Celada,

1
Penso che David Kohen abbia ragione ad un certo punto. Questo è un modo per implementare copy-on-write. L'essenza sarebbe che con questo segno, scrivere su quella pagina avrebbe innescato un gestore di errori di pagina che avrebbe quindi preso le misure appropriate, cioè copia su scrittura. Purtroppo questo dettaglio (che sarebbe specifico del sistema) è per lo più irrilevante per la domanda. Tieni presente che CoW ha due dimensioni: quella visibile al processo e quella di come il kernel potrebbe implementarlo.
0xC0000022L
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.