기록 중 복사 란 무엇입니까?


134

COW (Copy-On-Write)가 무엇이며 어떤 용도로 사용되는지 알고 싶습니다. Sun JDK 튜토리얼에서 'write-on-write array'라는 용어가 여러 번 언급되었지만 그 의미를 이해하지 못했습니다.

답변:


156

나는 내 자신의 설명을 작성하려고했지만 이 위키 백과 기사는 거의 요약합니다.

기본 개념은 다음과 같습니다.

COW (Copy-On-Write) ( "COW"라고도 함)는 컴퓨터 프로그래밍에 사용되는 최적화 전략입니다. 근본적인 아이디어는 여러 명의 발신자가 처음에 구분할 수없는 리소스를 요청하는 경우 동일한 리소스에 대한 포인터를 제공 할 수 있다는 것입니다. 이 기능은 호출자가 리소스의 "복사본"을 수정하려고 할 때까지 유지 관리 할 수 ​​있으며,이 시점에서 변경 사항이 다른 사람에게 보이지 않도록 진정한 개인 복사본이 만들어집니다. 이 모든 것은 발신자에게 투명하게 발생합니다. 가장 큰 장점은 호출자가 수정하지 않으면 개인 복사본을 만들 필요가 없다는 것입니다.

또한 다음은 일반적인 COW 응용 프로그램입니다.

COW 개념은 Microsoft SQL Server 2005와 같은 데이터베이스 서버에서 인스턴트 스냅 샷을 유지 관리하는 데에도 사용됩니다. 인스턴트 스냅 샷은 기본 데이터가 업데이트 될 때 데이터의 사전 수정 사본을 저장하여 데이터베이스의 정적 뷰를 유지합니다. 인스턴트 스냅 샷은 테스트 용도 또는 순간 별 보고서를 테스트하는 데 사용되며 백업을 대체하는 데 사용해서는 안됩니다.


일반 배열이 사용되는 모든 항목이 있지만 일부 상황에서는 이러한 유형의 전략이보다 최적화 된 결과를 낳습니다.
Andrew Flanagan

3
@ hhafez : 리눅스는 clone()구현에 사용할 때 그것을 사용 합니다 fork()-부모 프로세스의 메모리는 자식을 위해 결합됩니다.
Kerrek SB

@hhafez 일부 파일 시스템은 CoW를 사용합니다 (예 : BTRFS) .
Geremia

이것이 SandboxIE의 작동 방식입니까? 샌드 박스 프로그램이 무언가를 덮어 쓰려고 할 때 샌드 박스가 파일 시스템 작업을 가로 채서 파일을 샌드 박스 폴더에 복사하고 프로그램이 원본 대신 샌드 박스 파일에 쓸 수있게합니다. 쓰기시 복사라고합니까?
Ronnie Matthews

병합은 결국 어떻게 이루어 집니까? N 개의 사본이있는 경우 어떤 디스크를 결국 디스크에 저장합니까?
SimpleGuy

59

"쓰기시 복사"는 거의 비슷한 소리를 의미합니다. 모든 사람이 기록 될 때까지 동일한 데이터의 단일 공유 사본 을 가지고 사본이 만들어집니다. 일반적으로 쓰기시 복사는 동시성 문제를 해결하는 데 사용됩니다. 예를 들어 ZFS 에서는 디스크의 데이터 블록에 기록 중 복사가 할당됩니다. 변경 사항이 없으면 원래 블록을 유지합니다. 변경 사항은 영향을받는 블록 만 변경했습니다. 이는 최소 개수의 새 블록이 할당됨을 의미합니다.

이러한 변경 사항은 일반적으로 트랜잭션 방식으로 구현됩니다 . 즉, ACID 속성이 있습니다. 이렇게하면 모든 동시성 문제가 제거됩니다. 모든 업데이트가 원자 성임을 보증하기 때문입니다.


1
변경하면 다른 사람에게 새 사본을 어떻게 알립니 까? 그들이 잘못된 데이터를 보지 않겠습니까?
powder366

12
@ powder366-아니요. 실제로 사본을 만들 때 변경을 할 때 잘못된 데이터가 표시되지 않습니다. 예를 들어,라는 데이터 블록이 있습니다 A. 프로세스 1, 2, 3, 4각 희망은 그것의 복사본을 만들고 시스템 아무것도 복사되지 않습니다 아직 모든 것이 여전히 읽고 "쓰기에서 복사"는에, 그것을 읽기 시작합니다 A. 이제 공정 3의 그것의 복사본을 변경하고 싶어 A, 과정을 3실제로 지금의 사본을 만들 것입니다 A및라는 새로운 데이터 블록을 만듭니다 B. 프로세스 1, 2, 4여전히 블록 읽는 A과정은 3지금 읽고있다 B.
Puddler

1
@Puddler 'A'에서 변경하면 어떻게 될까요? 모든 프로세스가 업데이트 된 정보를 읽거나 오래된 것입니까?
개발자

3
@Developer : 어떤 프로세스를 변경하든 A새 복사본을 만들어야합니다. 완전히 새로운 프로세스가 등장하고 변경되면 어떻게 될지 묻는 A다면 내 설명은 실제로 그에 대해 충분히 자세하게 설명되지 않습니다. 이는 구현에 따라
다르며

10

Copy-on-Write에 대해 동일한 대답을 반복하지 않습니다. 앤드류의 대답찰리의 대답 은 이미 매우 분명 하다고 생각 합니다. 이 개념이 얼마나 광범위하게 사용되는지 언급하기 위해 OS 세계의 예를 들겠습니다.

새로운 프로세스를 사용 fork()하거나 vfork()만들 수 있습니다 . vfork는 COW (Copy-On-Write) 개념을 따릅니다. 예를 들어 vfork에서 생성 한 자식 프로세스는 부모 프로세스와 데이터 및 코드 세그먼트를 공유합니다. 이것은 포크 시간을 단축시킵니다. exec와 vfork를 수행하는 경우 vfork를 사용해야합니다. 따라서 vfork는 부모와 데이터 및 코드 세그먼트를 공유하는 자식 프로세스를 생성하지만 exec를 호출하면 자식 프로세스의 주소 공간에 새 실행 파일의 이미지가로드됩니다.


3
"vfork는 기록 중 복사의 개념을 따릅니다." 이 줄을 바꾸어보십시오. vforkCOW를 사용하지 않습니다. 실제로 아이가 무언가를 쓰면 정의되지 않은 동작이 발생하고 페이지가 복사되지 않을 수 있습니다 !! 사실, 당신은 다른 방법으로 말하는 것이 사실이라고 말할 수 있습니다. COW는 vfork공유 공간에서 무언가가 수정 될 때까지 작동 합니다!
Pavan Manjunath

Pavan에 완전히 동의하십시오. "vfork는 copy-on-write의 개념을 따릅니다"행을 제거하십시오. 이제 COW는 포크에서 최적화로 사용되므로 vfork처럼 작동하고 자식 프로세스에 대한 부모 데이터의 사본을 만들지 않습니다 (우리는 자식에서 exec * 만 호출하는 경우)
Shekhar Kumar

7

다른 예를 제공하기 위해 Mercurial은 COW (Copy-On-Write) 를 사용하여 로컬 리포지토리 복제를 실제로 "저렴한"작업으로 만듭니다.

원칙은 메모리의 객체 대신 물리적 파일에 대해 이야기한다는 점을 제외하고 다른 예제와 동일합니다. 처음에 복제본은 복제본이 아니라 원본에 대한 하드 링크 입니다. 클론에서 파일을 변경하면 새 버전을 나타내는 사본이 작성됩니다.


2

내가 발견 너무 COW 언급 PHP에서 zval에 대한 좋은 기사를 :

Copy On Write (약칭 'COW')는 메모리 절약을 위해 고안된 기술입니다. 소프트웨어 엔지니어링에서 더 일반적으로 사용됩니다. 이는 이미 zval을 가리키는 기호에 쓸 때 PHP가 메모리를 복사하거나 새로운 메모리 영역을 할당한다는 것을 의미합니다.


0

또한 Ruby 'Enterprise Edition'에서도 메모리를 깔끔하게 저장하는 데 사용됩니다.


2
나는 그가 그런 의미에서 "사용"을 의미하지 않았다고 생각합니다.
spydon

0

좋은 예는 전략을 사용하여 얼룩을 저장하는 Git입니다. 왜 해시를 사용합니까? 부분적으로 차이를 쉽게 수행 할 수 있지만 COW 전략을 최적화하기가 더 간단하기 때문입니다. 파일을 거의 변경하지 않고 새로 커밋하면 개체와 트리의 대부분이 변경되지 않습니다. 따라서 커밋은 해시로 만든 다양한 포인터를 통해 이미 존재하는 많은 객체를 참조하여 전체 기록을 저장하는 데 필요한 저장 공간을 훨씬 작게 만듭니다.


0

메모리 보호 개념입니다. 이 컴파일러에서는 하위의 데이터를 수정하기 위해 추가 사본을 작성하며이 업데이트 된 데이터는 상위 데이터에 반영되지 않습니다.


0

다음은 데코레이터 디자인 패턴을 사용한 COW (Copy-On-Write) Python 구현 입니다 . 불변 Value객체에 대한 참조 는 가변 CowValue객체 (데코레이터)에 의해 유지됩니다 . CowValue목적은 앞으로 모든 불변의 요청 읽어 Value새로운 불변 작성하여 객체와 차단 모든 쓰기 요청을 Value올바른 상태로 개체를. CowValue객체는 얕은는 공유 할 수 있도록 변수 사이에 복사해야합니다 Value개체를.

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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.