O que é copiar na gravação?


133

Gostaria de saber o que é copiar em gravação e para que é usado? O termo 'matriz de copiar na gravação' é mencionado várias vezes nos tutoriais do Sun JDK, mas eu não entendi o que isso significava.

Respostas:


155

Eu ia escrever minha própria explicação, mas este artigo da Wikipedia resume bastante.

Aqui está o conceito básico:

A cópia na gravação (às vezes chamada de "COW") é uma estratégia de otimização usada na programação de computadores. A idéia fundamental é que, se vários chamadores solicitarem recursos inicialmente indistinguíveis, você poderá fornecer indicadores para o mesmo recurso. Essa função pode ser mantida até que um chamador tente modificar sua "cópia" do recurso, quando uma cópia privada verdadeira é criada para impedir que as alterações fiquem visíveis para todos os outros. Tudo isso acontece de forma transparente para os chamadores. A principal vantagem é que, se um chamador nunca fizer nenhuma modificação, nenhuma cópia privada será criada.

Também aqui está uma aplicação de um uso comum do COW:

O conceito COW também é usado na manutenção de instantâneos instantâneos em servidores de banco de dados como o Microsoft SQL Server 2005. Os instantâneos instantâneos preservam uma visão estática de um banco de dados, armazenando uma cópia de pré-modificação dos dados quando os dados subjacentes são atualizados. Instantâneos instantâneos são usados ​​para testes de uso ou relatórios dependentes de momento e não devem ser usados ​​para substituir backups.


qualquer coisa que uma matriz regular seja usada ... no entanto, em algumas situações, esse tipo de estratégia resulta em resultados mais otimizados.
Andrew Flanagan

3
@hafez: o Linux usa quando clone()implementa fork()- a memória do processo pai é COW para a criança.
precisa saber é o seguinte

@hhafez Alguns sistemas de arquivos usam CoW, por exemplo, BTRFS .
Geremia

É assim que o SandboxIE funciona? quando um programa em área restrita deseja substituir algo, o sandbox intercepta a operação do sistema de arquivos e copia o arquivo para a pasta área restrita e permite que o programa grave no arquivo protegido em vez do original. Isso se chama Copiar na gravação?
Ronnie Matthews

Como a fusão acontece eventualmente? Se houver N cópias, qual delas será mantida para salvar no disco, digamos?
SimpleGuy

59

"Copiar na gravação" significa mais ou menos o que parece: todos têm uma única cópia compartilhada dos mesmos dados até que sejam gravados e, em seguida, uma cópia é feita. Geralmente, a cópia na gravação é usada para resolver os tipos de problemas de simultaneidade. No ZFS , por exemplo, os blocos de dados no disco são alocados na cópia; contanto que não haja alterações, você mantém os blocos originais; uma mudança alterou apenas os blocos afetados. Isso significa que o número mínimo de novos blocos é alocado.

Essas alterações também são geralmente implementadas para serem transacionais , ou seja, elas têm as propriedades ACID . Isso elimina alguns problemas de simultaneidade, porque você garante que todas as atualizações são atômicas.


1
Se você fizer uma alteração, como o outro é notificado da sua nova cópia? Eles não veriam os dados errados.
powder366

12
@ powder366 - Não, eles não veriam os dados errados porque quando você faz uma alteração é quando uma cópia é realmente feita. Por exemplo, você tem um bloco de dados chamado A. Processo 1, 2, 3, 4cada um quer fazer uma cópia do mesmo e começar a lê-lo, em uma "cópia na escrita" Sistema nada é copiado mas tudo ainda está lendo A. Agora, o processo 3deseja alterar sua cópia A, 3agora o processo efetua uma cópia Ae cria um novo bloco de dados chamado B. Processo 1, 2, 4ainda está lendo bloco Aprocesso 3está agora lendo B.
Puddler

1
@Puddler o que acontecerá se forem feitas alterações em 'A'. Todos os processos estarão lendo as informações atualizadas ou antigas?
Desenvolvedor

3
@ Desenvolvedor: Bem, qualquer processo que esteja fazendo uma alteração Adeve estar criando uma nova cópia. Se você está perguntando o que acontece se um processo totalmente novo surgir e mudar A, minha explicação não entra em detalhes suficientes para isso. Isso seria implementação específica e exigem conhecimento sobre como você deseja que o resto da aplicação ao trabalho, tais como arquivo \ bloqueio de dados, etc.
Puddler

10

Não repetirei a mesma resposta em Copy-on-Write. Acho que a resposta de Andrew e a de Charlie já deixaram muito claro. Vou dar um exemplo do mundo do SO, apenas para mencionar o quão amplamente esse conceito é usado.

Podemos usar fork()ou vfork()criar um novo processo. O vfork segue o conceito de cópia na gravação. Por exemplo, o processo filho criado pelo vfork compartilhará o segmento de dados e código com o processo pai. Isso acelera o tempo de bifurcação. Espera-se usar o vfork se você estiver executando exec seguido pelo vfork. Portanto, o vfork criará o processo filho que compartilhará os dados e o segmento de código com seu pai, mas quando chamamos exec, ele carregará a imagem de um novo executável no espaço de endereço do processo filho.


3
"o vfork segue o conceito de cópia na gravação". Por favor, considere alterar esta linha. vforkNÃO usa VACA. De fato, se a criança escreve algo, pode resultar em comportamento indefinido e não copiar páginas! De fato, você pode dizer que o contrário é verdade. COW age como vforkaté que algo seja modificado no espaço compartilhado!
Pavan Manjunath

Concordo totalmente com Pavan. Remova as linhas "vfork segue o conceito de cópia na gravação". Agora, um dia, COW é usado no garfo como uma otimização, de modo que ele age como vfork e não fazer uma cópia dos dados do pai para o processo de criança (se apenas chamadas * exec em criança)
Shekhar Kumar

7

Apenas para dar outro exemplo, o Mercurial usa a cópia na gravação para tornar a clonagem de repositórios locais uma operação realmente "barata".

O princípio é o mesmo dos outros exemplos, exceto que você está falando sobre arquivos físicos em vez de objetos na memória. Inicialmente, um clone não é uma duplicata, mas um vínculo físico com o original. Conforme você altera os arquivos no clone, as cópias são gravadas para representar a nova versão.


2

Encontrei este bom artigo sobre o zval no PHP, que também mencionou o COW:

Copy On Write (abreviado como 'COW') é um truque projetado para economizar memória. É usado de maneira mais geral na engenharia de software. Isso significa que o PHP copiará a memória (ou alocará nova região de memória) quando você escrever em um símbolo, se este já estiver apontando para um zval.


0

Também é usado no Ruby 'Enterprise Edition' como uma maneira elegante de economizar memória.


2
Eu não acho que ele quis dizer "usado para" nesse sentido.
Spydon # 5/15

0

Um bom exemplo é o Git, que usa uma estratégia para armazenar blobs. Por que ele usa hashes? Em parte porque essas são mais fáceis de executar, mas também porque simplifica a otimização de uma estratégia de COW. Quando você faz um novo commit com poucos arquivos, a grande maioria dos objetos e as árvores não são alteradas. Portanto, o commit, através de vários ponteiros feitos de hashes, fará referência a um monte de objetos que já existem, tornando o espaço de armazenamento necessário para armazenar todo o histórico muito menor.


0

É um conceito de proteção de memória. Neste compilador, cria uma cópia extra para modificar os dados no filho e esses dados atualizados não refletem nos dados dos pais.


0

A seguir, é apresentada uma implementação Python de copiar-em-gravar (COW), usando o padrão de design do decorador . Uma referência a um Valueobjeto imutável é mantida por um CowValueobjeto mutável (o decorador). O CowValueobjeto encaminha todas as solicitações de leitura para o Valueobjeto imutável e intercepta todas as solicitações de gravação criando um novo Valueobjeto imutável com o estado correto. O CowValueobjeto deve ser copiado superficialmente entre as variáveis ​​para permitir o compartilhamento do 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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.