Copy-on-write

Da Wikipedia, l'enciclopedia libera.

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[modifica | modifica wikitesto]

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 non si rende realmente necessaria, ovvero 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[modifica | modifica wikitesto]

Virtualizzazione delle risorse[modifica | modifica wikitesto]

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 IX l'identificatore di una generica risorsa virtuale;
  • con la scrittura IX -> R l'associazione intercorrente tra l'identificatore IX e la risorsa fisica R.

Duplicazione della risorsa virtuale[modifica | modifica wikitesto]

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

  • IA -> R1

Quando il sistema riceve la richiesta di duplicare la risorsa virtuale IA, viene generata una nuova risorsa virtuale IB ma non viene creata alcuna nuova risorsa fisica: il nuovo identificatore viene anch'esso associato alla risorsa fisica R1:

  • IA -> R1
  • IB -> R1

La risorsa fisica R1 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 IA e IB.

Per una corretta gestione del copy-on-write il sistema deve tenere traccia del fatto che IA e IB non stanno realmente condividendo la risorsa fisica R1, e che pertanto un eventuale tentativo di accedere in scrittura alla risorsa tramite uno qualsiasi di essi deve essere intercettata e opportunamente gestita in modo da non ripercuotersi sugli altri.[1]

Scrittura di una risorsa virtuale[modifica | modifica wikitesto]

Ipotizzando che si renda necessaria un'operazione di scrittura (ad esempio sulla risorsa virtuale IA), 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 R2 come copia di R1
  • associa l'identificatore IA a R2

A questo punto il sistema si trova nel seguente stato:

  • IA -> R2
  • IB -> R1

L'operazione di scrittura inizialmente sospesa può quindi proseguire, modificando lo stato di R2 senza interferire con quello di R1, che continua ad essere accessibile tramite l'identificatore IB.

Principali applicazioni[modifica | modifica wikitesto]

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[modifica | modifica wikitesto]

  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[modifica | modifica wikitesto]

Altri progetti[modifica | modifica wikitesto]

Collegamenti esterni[modifica | modifica wikitesto]