¿Qué es copiar en escritura?

133

¿Me gustaría saber qué es copiar y escribir y para qué se utiliza? El término "matriz de copia en escritura" se menciona varias veces en los tutoriales de Sun JDK, pero no entendí lo que significaba.

hhafez
fuente

Respuestas:

155

Iba a escribir mi propia explicación, pero este artículo de Wikipedia lo resume bastante.

Aquí está el concepto básico:

Copiar en escritura (a veces denominado "VACA") es una estrategia de optimización utilizada en la programación de computadoras. La idea fundamental es que si varias personas que llaman solicitan recursos que inicialmente no se pueden distinguir, puede darles punteros al mismo recurso. Esta función se puede mantener hasta que la persona que llama intente modificar su "copia" del recurso, momento en el que se crea una copia privada verdadera para evitar que los cambios sean visibles para todos los demás. Todo esto sucede de manera transparente a las personas que llaman. La principal ventaja es que si la persona que llama nunca realiza modificaciones, no es necesario crear una copia privada.

También aquí hay una aplicación de un uso común de VACA:

El concepto COW también se utiliza en el mantenimiento de instantáneas instantáneas en servidores de bases de datos como Microsoft SQL Server 2005. Las instantáneas instantáneas conservan una vista estática de una base de datos al almacenar una copia de datos previa a la modificación cuando se actualizan los datos subyacentes. Las instantáneas instantáneas se usan para probar usos o informes dependientes del momento y no se deben usar para reemplazar las copias de seguridad.

Andrew Hare
fuente
cualquier cosa para la que se use una matriz regular ... sin embargo, en algunas situaciones, este tipo de estrategia da como resultado resultados más optimizados.
Andrew Flanagan
3
@hhafez: Linux lo usa cuando se clone()implementa fork(): la memoria del proceso principal está COWed para el hijo.
Kerrek SB
@hhafez Algunos sistemas de archivos usan CoW, por ejemplo, BTRFS .
Geremia
¿Es así como funciona SandboxIE? cuando un programa de espacio aislado quiere sobrescribir algo, sandboxie intercepta la operación del sistema de archivos y copia el archivo en la carpeta de espacio aislado y deja que el programa escriba en el archivo de espacio aislado en lugar del original. ¿Eso se llama Copia al escribir?
Ronnie Matthews
¿Cómo sucede la fusión eventualmente? Si hay N copias, ¿cuál se guarda finalmente para guardar en dicho disco?
SimpleGuy
59

"Copiar al escribir" significa más o menos lo que parece: todos tienen una sola copia compartida de los mismos datos hasta que se escribe , y luego se hace una copia. Por lo general, la copia en escritura se utiliza para resolver problemas de concurrencia. En ZFS , por ejemplo, los bloques de datos en el disco se asignan copia en escritura; mientras no haya cambios, conserva los bloques originales; un cambio solo cambió los bloques afectados. Esto significa que se asigna el número mínimo de nuevos bloques.

Estos cambios también suelen implementarse para ser transaccionales , es decir, tienen las propiedades ACID . Esto elimina algunos problemas de concurrencia, porque entonces está garantizado que todas las actualizaciones son atómicas.

Charlie Martin
fuente
1
Si realiza un cambio, ¿cómo se notifica al otro de su nueva copia? ¿No verían los datos incorrectos?
powder366
12
@ powder366 - No, no verían los datos incorrectos porque cuando haces un cambio es cuando realmente se hace una copia. Por ejemplo, tiene un bloque de datos llamado A. Proceso 1, 2, 3, 4cada uno desea hacer una copia del mismo y empezar a leerlo, en una "copia en escritura" sistema nada es copiado sin embargo, todo lo que todavía está leyendo A. Ahora el proceso 3quiere hacer un cambio en su copia A, el proceso 3ahora hará una copia Ay creará un nuevo bloque de datos llamado B. Proceso 1, 2, 4todavía está leyendo bloque de Aproceso 3es ahora la lectura B.
Puddler
1
@Puddler, ¿qué sucederá si se realizan cambios en 'A'? Todos los procesos estarán leyendo la información actualizada o antigua?
Desarrollador
3
@Developer: Bueno, sea cual sea el proceso en el que se realice un cambio, se Adebe crear una nueva copia. Si está preguntando qué sucede si aparece un proceso completamente nuevo y cambia, Aentonces mi explicación realmente no entra en suficientes detalles para eso. Eso sería de aplicación específica y requieren conocimientos sobre cómo desea que el resto de la aplicación al trabajo, tales como archivo \ bloqueo de datos, etc.
Puddler
10

No repetiré la misma respuesta en Copy-on-Write. Creo que la respuesta de Andrew y la respuesta de Charlie ya han dejado muy claro. Le daré un ejemplo del mundo del sistema operativo, solo para mencionar cuán ampliamente se usa este concepto.

Podemos usar fork()o vfork()crear un nuevo proceso. vfork sigue el concepto de copia en escritura. Por ejemplo, el proceso hijo creado por vfork compartirá los datos y el segmento de código con el proceso padre. Esto acelera el tiempo de bifurcación. Se espera que use vfork si está ejecutando exec seguido de vfork. Entonces vfork creará el proceso hijo que compartirá datos y segmento de código con su padre pero cuando llamamos a exec, cargará la imagen de un nuevo ejecutable en el espacio de direcciones del proceso hijo.

Shamik
fuente
3
"vfork sigue el concepto de copia en escritura". Por favor considere cambiar esta línea. vforkNO usa VACA. De hecho, si el niño escribe algo, puede provocar un comportamiento indefinido y no copiar páginas. De hecho, puedes decir que al revés es algo cierto. ¡VACA actúa como vforkhasta que algo se modifica en el espacio compartido!
Pavan Manjunath
Completamente de acuerdo con Pavan. Elimine las líneas "vfork sigue el concepto de copia en escritura". Hoy en día, COW se usa en fork como una optimización, para que actúe como vfork y no haga una copia de los datos de los padres para el proceso secundario (si solo llamamos a exec * en secundario)
Shekhar Kumar
7

Solo para proporcionar otro ejemplo, Mercurial utiliza la copia en escritura para hacer que la clonación de repositorios locales sea una operación realmente "barata".

El principio es el mismo que el de los otros ejemplos, excepto que se trata de archivos físicos en lugar de objetos en la memoria. Inicialmente, un clon no es un duplicado sino un enlace rígido al original. A medida que cambia los archivos en el clon, se escriben copias para representar la nueva versión.

harpo
fuente
2

Encontré este buen artículo sobre zval en PHP, que también mencionaba COW:

Copiar al escribir (abreviado como 'VACA') es un truco diseñado para ahorrar memoria. Se usa más generalmente en ingeniería de software. Significa que PHP copiará la memoria (o asignará una nueva región de memoria) cuando escriba en un símbolo, si este ya apuntaba a un zval.

Amir Shabani
fuente
0

También se usa en Ruby 'Enterprise Edition' como una forma ordenada de ahorrar memoria.

Chris
fuente
2
No creo que quisiera decir "usado para" en ese sentido.
Spydon
0

Un buen ejemplo es Git, que utiliza una estrategia para almacenar blobs. ¿Por qué usa hashes? En parte porque estos son más fáciles de realizar, pero también porque simplifica la optimización de una estrategia COW. Cuando realiza una nueva confirmación con pocos cambios de archivos, la gran mayoría de los objetos y árboles no cambiarán. Por lo tanto, el commit, a través de varios punteros hechos de hashes, hará referencia a un grupo de objetos que ya existen, haciendo que el espacio de almacenamiento requerido para almacenar todo el historial sea mucho más pequeño.

Sam Keays
fuente
0

Es un concepto de protección de memoria. En este compilador, se crea una copia adicional para modificar los datos en el niño y estos datos actualizados no se reflejan en los datos de los padres.

Sushant
fuente
0

Aquí hay una implementación de Python de copia en escritura (COW) usando el patrón de diseño del decorador . Un objeto Valuemutable CowValue(el decorador) mantiene una referencia a un objeto inmutable . El CowValueobjeto reenvía todas las solicitudes de lectura al Valueobjeto inmutable e intercepta todas las solicitudes de escritura creando un nuevo Valueobjeto inmutable con el estado correcto. El CowValueobjeto debe copiarse superficialmente entre las variables para permitir compartir el Valueobjeto.

import abc
import copy

class BaseValue(abc.ABC):
    @abc.abstractmethod
    def read(self):
        raise NotImplementedError
    @abc.abstractmethod
    def write(self, data):
        raise NotImplementedError

class Value(BaseValue):
    def __init__(self, data):
        self.data = data
    def read(self):
        return self.data
    def write(self, data):
        pass

class CowValue(BaseValue):
    def __init__(self, data):
        self.value = Value(data)
    def read(self):
        return self.value.read()
    def write(self, data):
        self.value = Value(data)

v = CowValue(1)
w = copy.copy(v)  # shares the immutable Value object
assert v.read() == w.read()
assert id(v.value) == id(w.value)
w.write(2)  # creates a new immutable Value object with the correct state
assert v.read() != w.read()
assert id(v.value) != id(w.value)
Maggyero
fuente