Copy-on-write

La cosiddetta strategia copy-on-write (espressione inglese approssimativamente traducibile con "copia in caso di scrittura") è una tecnica di ottimizzazione informatica mirante alla riduzione delle operazioni di duplicazione delle risorse del sistema (generalmente strutture dati o aree di memoria) attraverso l'eliminazione delle copie non necessarie.

Principio di funzionamento

Durante lo svolgimento delle normali operazioni di un programma o di un sistema operativo è possibile che si renda necessaria la duplicazione di una risorsa, ovvero la creazione di una nuova risorsa avente contenuto iniziale (o, più genericamente, stato iniziale) identico a quello dell'originale.

Immediatamente dopo la duplicazione e per tutto il tempo in cui nessuna delle due risorse viene modificata, esse sono, di fatto, indistinguibili; durante questo lasso di tempo la reale esistenza di due copie indipendenti non è strettamente necessaria: il sistema può limitarsi a simulare l'operazione di duplicazione, mantenendo l'esistenza di un'unica copia e gestendo attraverso di essa, in modo del tutto trasparente ai richiedenti, tutte le operazioni di lettura destinate ad una qualsiasi delle due.

La vera e propria duplicazione della risorsa può essere posticipata fino al momento in cui l'esistenza di due risorse indipendenti si rende realmente necessaria, cioè in corrispondenza di un'operazione di modifica dello stato (generalmente la scrittura di un nuovo contenuto, da cui il nome di copy-on-write) di una qualsiasi delle copie fittizie.

Il vantaggio principale della strategia copy-on-write risiede nel fatto che se una risorsa duplicata viene successivamente liberata o distrutta senza che nel frattempo né l'originale né la copia siano mai stati modificati, il sistema ha effettivamente evitato una duplicazione non necessaria, con conseguente risparmio di tempo. Il copy-on-write è quindi tanto più vantaggioso quanto più onerosa è l'operazione di duplicazione e quanto più infrequenti sono le operazioni di scrittura.

Implementazione

Virtualizzazione delle risorse

L'implementazione di una strategia copy-on-write impone che, nel sistema, l'identificazione delle risorse interessate sia svincolata ed indipendente (almeno dal punto di vista degli utilizzatori) dalla loro effettiva collocazione fisica; è cioè necessario che tali risorse siano virtualizzate.

Ciò che gli utilizzatori conoscono ed usano è un identificatore di risorsa virtuale, attraverso il quale richiedere al sistema l'accesso alla risorsa; il sistema, per parte sua, associa ciascun identificatore alle informazioni necessarie per poter accedere alla vera e propria risorsa fisica. Nel seguito si indicheranno convenzionalmente:

  • con I X {\displaystyle I_{X}} l'identificatore di una generica risorsa virtuale;
  • con la scrittura I X R {\displaystyle I_{X}\rightarrow R} l'associazione intercorrente tra l'identificatore I X {\displaystyle I_{X}} e la risorsa fisica R {\displaystyle R} .

Duplicazione della risorsa virtuale

Nella situazione normale, ogni risorsa fisica è associata ad un unico identificatore:

  • I A R 1 {\displaystyle I_{A}\rightarrow R_{1}}

Quando il sistema riceve la richiesta di duplicare la risorsa virtuale I A {\displaystyle I_{A}} , viene generata una nuova risorsa virtuale I B {\displaystyle I_{B}} ma non viene creata alcuna nuova risorsa fisica: il nuovo identificatore viene anch'esso associato alla risorsa fisica R 1 {\displaystyle R_{1}} :

  • I A R 1 {\displaystyle I_{A}\rightarrow R_{1}}
  • I B R 1 {\displaystyle I_{B}\rightarrow R_{1}}

La risorsa fisica R 1 {\displaystyle R_{1}} non viene ancora duplicata: a partire da questo momento essa diventa la rappresentazione concreta, uguale ed indistinguibile, di entrambe le risorse virtuali, e attraverso di essa il sistema gestisce tutti gli accessi in lettura effettuati tramite gli identificatori I A {\displaystyle I_{A}} e I B {\displaystyle I_{B}} .

Per una corretta gestione del copy-on-write il sistema deve tenere traccia del fatto che I A {\displaystyle I_{A}} e I B {\displaystyle I_{B}} non stanno realmente condividendo la risorsa fisica R 1 {\displaystyle R_{1}} , e che pertanto un eventuale tentativo di accedere in scrittura alla risorsa tramite uno qualsiasi di essi deve essere intercettato e opportunamente gestito in modo da non ripercuotersi sugli altri.[1]

Scrittura di una risorsa virtuale

Ipotizzando che si renda necessaria un'operazione di scrittura (ad esempio sulla risorsa virtuale I A {\displaystyle I_{A}} ), il sistema constata che tale identificatore si riferisce ad una risorsa fisica condivisa in regime di copy-on-write e conseguentemente:

  • intercetta e sospende l'operazione di scrittura
  • crea una nuova risorsa fisica R 2 {\displaystyle R_{2}} come copia di R 1 {\displaystyle R_{1}}
  • associa l'identificatore I A {\displaystyle I_{A}} a R 2 {\displaystyle R_{2}}

A questo punto il sistema si trova nel seguente stato:

  • I A R 2 {\displaystyle I_{A}\rightarrow R_{2}}
  • I B R 1 {\displaystyle I_{B}\rightarrow R_{1}}

L'operazione di scrittura inizialmente sospesa può quindi proseguire, modificando lo stato di R 2 {\displaystyle R_{2}} senza interferire con quello di R 1 {\displaystyle R_{1}} , che continua ad essere accessibile tramite l'identificatore I B {\displaystyle I_{B}} .

Principali applicazioni

La tecnica del copy-on-write è spesso utilizzata dai sistemi operativi per la gestione delle pagine di memoria in regime di memoria virtuale: le pagine condivise possono essere marcate come di sola lettura in modo tale che gli accessi in scrittura vengano intercettati dalla MMU del processore, che solleva un'eccezione e passa il controllo ad un'apposita funzione di gestione del kernel che provvede alla duplicazione fisica della pagina interessata prima che la scrittura venga ripresa ed eseguita.

Il copy-on-write può ad esempio essere sfruttato quando un processo richiede (attraverso la chiamata di sistema fork o analoga) la creazione di un nuovo processo figlio, inizialmente identico a sé stesso,[2] oppure per ottimizzare la creazione di buffer di grandi dimensioni, in particolare se sparsi.[3]

Note

  1. ^ Diverso il caso di reale condivisione della risorsa, in cui è invece normale e previsto che qualsiasi modifica effettuata tramite un qualsiasi identificatore ad essa associata risulti visibile anche attraverso tutti gli altri.
  2. ^ Il vantaggio di tale approccio è particolarmente evidente nei sistemi in cui il caricamento in memoria di un nuovo programma è scomposto nelle due operazioni di fork ed exec: il processo figlio originante dalla fork non necessita davvero della copia dei dati del processo originale, giacché la successiva chiamata ad exec li sostituirà quasi immediatamente con quelli del nuovo programma.
  3. ^ Grandi buffer inizializzati a zero, quali quelli prodotti dalla funzione calloc in C, possono essere simulati dal sistema facendo puntare tutte le pagine virtuali di memoria necessarie a contenerlo verso un'unica pagina fisica contenente soli byte nulli; solo in seguito, se e quando l'applicazione tenterà di scrivere in tale buffer, il sistema provvederà ad allocare fisicamente le pagine di memoria strettamente necessarie.

Voci correlate

Altri progetti

Altri progetti

  • Wikibooks
  • Wikimedia Commons
  • Collabora a Wikibooks Wikibooks contiene esempi di implementazione in C++ del Copy-on-write
  • Collabora a Wikimedia Commons Wikimedia Commons contiene immagini o altri file su Copy-on-write

Collegamenti esterni

  • (EN) Jonathan M. Smith, Gerald Q. Maguire, Effects of copy-on-write memory management on the response time of UNIX fork operations (PDF), in Computing Systems, vol. 1, n. 3, 1988, pp. 225-278. URL consultato il 25 aprile 2009.
  Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica