Yazma üzerine kopyalama nedir?


134

Yazılı kopyanın ne olduğunu ve ne için kullanıldığını bilmek istiyorum. Sun JDK eğitimlerinde 'yazma üzerine kopyalama dizisi' teriminden birkaç kez bahsediliyor, ancak bunun ne anlama geldiğini anlamadım.

Yanıtlar:


156

Kendi açıklamamı yazacaktım ama bu Wikipedia makalesi bunu hemen hemen özetliyor.

İşte temel kavram:

Yazma üzerine kopyalama (bazen "COW" olarak anılır), bilgisayar programlamasında kullanılan bir optimizasyon stratejisidir. Temel fikir, eğer birden çok arayan başlangıçta ayırt edilemeyen kaynaklar isterse, onlara aynı kaynağa işaretçiler verebilirsiniz. Bu işlev, arayan kişi kaynağın "kopyasını" değiştirmeye çalışıncaya kadar sürdürülebilir, bu noktada değişikliklerin diğer herkes tarafından görülebilir olmasını önlemek için gerçek bir özel kopya oluşturulur. Tüm bunlar arayanlara şeffaf bir şekilde gerçekleşir. Birincil avantaj, arayan kişi hiçbir zaman değişiklik yapmazsa, özel bir kopya oluşturulmasına gerek olmamasıdır.

Ayrıca burada COW'nin yaygın kullanımının bir uygulaması:

COW kavramı, Microsoft SQL Server 2005 gibi veritabanı sunucularında anlık anlık görüntünün bakımında da kullanılır. Anlık anlık görüntüler, alt katman verileri güncellendiğinde verilerin bir ön değişiklik kopyasını depolayarak bir veritabanının statik görünümünü korur. Anlık anlık görüntüler, kullanımları veya ana bağlı raporları test etmek için kullanılır ve yedeklerin yerini almak için kullanılmamalıdır.


normal bir dizinin kullanıldığı herhangi bir şey ... bununla birlikte, bazı durumlarda, bu tür bir strateji daha optimize sonuçlarla sonuçlanır.
Andrew Flanagan

3
@hhafez: Linux, clone()uygulamak için kullandığında onu kullanır fork()- ana sürecin hafızası çocuk için COW'dur.
Kerrek SB

@hhafez Bazı dosya sistemleri CoW kullanır, örneğin BTRFS .
Geremia

SandboxIE böyle mi çalışıyor? sandboxie korumalı bir program bir şeyin üzerine yazmak istediğinde, sandboxie dosya sistemi işlemini durdurur ve dosyayı sanal alan klasörüne kopyalar ve programın orijinal yerine korumalı alandaki dosyaya yazmasına izin verir. Buna Yazarken Kopyala mı deniyor?
Ronnie Matthews

Sonunda birleştirme nasıl olur? N kopya varsa, hangisi sonunda söz konusu diske kaydetmek için saklanır?
SimpleGuy

59

"Yazılırken kopyala", aşağı yukarı göründüğü anlamına gelir: herkes yazılana kadar aynı verilerin tek bir paylaşılan kopyasına sahiptir ve ardından bir kopya yapılır. Genellikle, eşzamanlılık gibi sorunları çözmek için yazma üzerine kopyalama kullanılır. Örneğin ZFS'de , disk üzerindeki veri blokları yazma üzerine kopyalama olarak tahsis edilir; değişiklik olmadığı sürece, orijinal blokları korursunuz; bir değişiklik yalnızca etkilenen blokları değiştirdi. Bu, minimum sayıda yeni blok tahsis edildiği anlamına gelir.

Bu değişiklikler ayrıca genellikle işlemsel olarak uygulanır , yani ACID özelliklerine sahiptirler. Bu, bazı eşzamanlılık sorunlarını ortadan kaldırır, çünkü o zaman tüm güncellemelerin atomik olduğu garanti edilir.


1
Bir değişiklik yaparsanız, diğeri yeni kopyanızdan nasıl haberdar edilir? Yanlış verileri görmezler mi?
powder366

12
@ powder366 - Hayır, yanlış verileri görmezler çünkü bir değişiklik yaptığınızda, bir kopya aslında yapılır. Örneğin, adlı bir veri bloğunuz var A. Süreç 1, 2, 3, 4her Talep bir kopyasını yapmak ve sistem hiçbir şey kopyalanır henüz her şey hala okuma "yazma sırasında kopyala" Bir de, okumaya başlamak için A. Şimdi işlem , 3kopyasında bir değişiklik yapmak istiyor A, işlem 3şimdi aslında bir kopyasını yapacak Ave adı verilen yeni bir veri bloğu oluşturacak B. Süreç 1, 2, 4hala blok okuduğunuz Asüreci 3şimdi okuyor B.
Puddler

1
@ Puddler 'A'da değişiklik yapılırsa ne olur. Tüm işlemler güncellenmiş bilgileri mi okuyacak yoksa eski mi?
Geliştirici

3
@Developer: Hangi süreçte değişiklik yapılıyorsa, Ayeni bir kopya oluşturmalı. Tamamen yeni bir süreç gelir ve değişirse ne olacağını soruyorsanız, Aaçıklamam bunun için yeterince ayrıntıya girmiyor. Bu, uygulamaya özgü olacaktır ve uygulamanın geri kalanının nasıl çalışmasını istediğiniz hakkında bilgi gerektirir, örneğin dosya \ veri kilitleme vb.
Puddler

10

Aynı cevabı Yazılırken Kopyala'da tekrar etmeyeceğim. Sanırım Andrew'un cevabı ve Charlie'nin cevabı bunu çok netleştirdi. Size işletim sistemi dünyasından bir örnek vereceğim, sadece bu kavramın ne kadar yaygın kullanıldığını belirtmek için.

Yeni bir süreç oluşturmak için fork()veya kullanabiliriz vfork(). vfork, yazma üzerine kopyalama kavramını izler. Örneğin, vfork tarafından oluşturulan alt süreç, verileri ve kod segmentini üst süreçle paylaşır. Bu, çatallanma süresini hızlandırır. Eğer exec ardından vfork yapıyorsanız, vfork kullanmanız beklenir. Dolayısıyla vfork, veriyi ve kod segmentini ebeveyniyle paylaşacak çocuk süreci yaratacak, ancak exec'yi çağırdığımızda, alt sürecin adres alanına yeni bir yürütülebilir dosyanın görüntüsünü yükleyecektir.


3
"vfork, yazma üzerine kopyalama kavramını izler". Lütfen bu satırı değiştirmeyi düşünün. vforkCOW KULLANMAZ. Aslında, çocuk bir şey yazarsa, bu tanımsız davranışlara neden olabilir ve sayfaların kopyalanmasına neden olmaz !! Aslında, tam tersi bir şekilde doğru diyebilirsiniz. COW vfork, paylaşılan alanda bir şey değiştirilene kadar davranır !
Pavan Manjunath

Pavan'a tamamen katılıyorum. "Vfork, yazma üzerine kopyalama kavramını izler" satırlarını kaldırın. Şimdi bir gün, COW bir optimizasyon olarak forkta kullanılıyor, böylece vfork gibi davranıyor ve çocuk süreç için ebeveyn verilerinin bir kopyasını oluşturmuyor (eğer çocukta sadece exec * çağırırsak)
Shekhar Kumar

7

Başka bir örnek vermek gerekirse, Mercurial yerel depoları klonlamayı gerçekten "ucuz" bir işlem haline getirmek için yazarken kopyala özelliğini kullanıyor .

İlke, bellekteki nesneler yerine fiziksel dosyalardan bahsetmeniz dışında diğer örneklerle aynıdır. Başlangıçta, bir klon bir kopya değil , orijinal ile sabit bir bağlantıdır . Klondaki dosyaları değiştirdiğinizde, kopyalar yeni sürümü temsil edecek şekilde yazılır.


2

PHP'de zval hakkında COW'dan da bahseden bu güzel makaleyi buldum :

Yazarken Kopyala ('COW' olarak kısaltılır) hafızadan tasarruf etmek için tasarlanmış bir numaradır. Daha genel olarak yazılım mühendisliğinde kullanılır. Bu, bir sembole yazarken PHP'nin belleği kopyalayacağı (veya yeni bellek bölgesi tahsis edeceği) anlamına gelir, eğer bu zaten bir zval'i gösteriyorsa.


0

Ayrıca Ruby 'Enterprise Edition'da bellek tasarrufu için temiz bir yol olarak kullanılır.


2
Bu anlamda "kullanılmış" demek istediğini sanmıyorum.
spydon

0

İyi bir örnek, blobları depolamak için bir strateji kullanan Git'tir. Neden karma kullanır? Kısmen bunların gerçekleştirilmesi daha kolay olduğu için, ancak aynı zamanda bir COW stratejisini optimize etmeyi kolaylaştırdığı için. Birkaç dosya değişikliği ile yeni bir işlem yaptığınızda, nesnelerin ve ağaçların büyük çoğunluğu değişmeyecektir. Bu nedenle commit, hashlerden oluşan çeşitli işaretçiler aracılığıyla zaten var olan bir nesneye referans verecek ve tüm geçmişi depolamak için gereken depolama alanını çok daha küçük hale getirecektir.


0

Hafıza koruma konseptidir. Bu derleyicide, alt öğedeki verileri değiştirmek için fazladan kopya oluşturur ve bu güncellenmiş veriler ebeveyn verilerine yansıtılmaz.


0

İşte bundan sonra, dekoratör tasarım modelini kullanan bir yazma üzerine kopyalama (COW) Python uygulaması . Değişmez bir Valuenesneye yapılan gönderme, değiştirilebilir bir CowValuenesne (dekoratör) tarafından tutulur . CowValueNesne ileri bütün değişmez yapılan okuma istekleri Valueyeni değişmez oluşturarak nesne ve yakaladığını tüm yazma isteklerini Valuedoğru devletle nesneyi. CowValueNesne sığ paylaşılmasına izin değişkenler arasında kopyalanması gerekir Valuenesne.

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.