Answers:
我本来要写我自己的解释,但是这篇Wikipedia文章几乎总结了一下。
这是基本概念:
写时复制(有时称为“ COW”)是计算机编程中使用的一种优化策略。基本思想是,如果多个调用方请求最初无法区分的资源,则可以为他们提供指向同一资源的指针。可以一直保持此功能,直到调用者尝试修改其资源的“副本”为止,此时将创建一个真正的私有副本,以防止其他所有人看到更改。所有这些对于呼叫者都是透明的。主要优点是,如果调用者从不进行任何修改,则无需创建私有副本。
这也是COW常用用法的应用程序:
COW概念还用于维护Microsoft SQL Server 2005等数据库服务器上的即时快照。即时快照通过在底层数据更新时存储数据的修改前副本来保留数据库的静态视图。即时快照用于测试用途或与时间相关的报告,并且不应用于替换备份。
clone()
用于实现时会使用它fork()
-子进程的父进程的内存是COWed的。
“写时复制”听起来或多或少意味着:每个人都有相同数据的单个共享副本,直到被写入为止,然后创建一个副本。通常,写时复制用于解决并发问题。例如,在ZFS中,磁盘上的数据块被分配为写时复制。只要没有变化,就保留原始块;更改仅更改了受影响的块。这意味着分配了最少数量的新块。
这些更改通常也实现为事务性的,即它们具有ACID属性。这消除了一些并发问题,因为这样可以保证所有更新都是原子更新。
A
。过程中1
,2
,3
,4
每个想拍它的一个副本,并开始阅读它,在“写时复制”系统没有被复制但一切都还在读书A
。现在,process 3
想要对其副本进行更改A
,process 3
实际上将对其进行副本A
并创建一个名为的新数据块B
。过程1
,2
,4
还在读块A
过程3
现在读取B
。
A
都应该创建一个新副本。如果您问一个全新的过程来了并且会发生变化,A
那会发生什么,那么我的解释就没有足够详细地说明了。这将是实现特定的,需要你是如何想的实施工作,如文件\数据锁定等其余知识
我不会在写复制时重复相同的答案。我认为安德鲁的答案和查理的答案已经很清楚了。我将为您提供来自OS世界的示例,仅提及此概念的使用范围。
我们可以使用fork()
或vfork()
创建一个新的过程。vfork遵循写时复制的概念。例如,由vfork创建的子进程将与父进程共享数据和代码段。这样可以加快分叉时间。如果要先执行exec,然后执行vfork,则应使用vfork。因此,vfork将创建子进程,该子进程将与其父进程共享数据和代码段,但是当我们调用exec时,它将在子进程的地址空间中加载新可执行文件的映像。
vfork
不使用COW。实际上,如果孩子写东西,可能会导致不确定的行为,并且无法复制页面!实际上,您可以说相反的说法是正确的。COW的行为就像vfork
在共享空间中对某些内容进行修改之前一样!
仅举另一个例子,Mercurial使用写时复制使克隆本地存储库成为真正的“廉价”操作。
除了要谈论物理文件而不是内存中的对象外,该原理与其他示例相同。最初,克隆不是重复的,而是与原始副本的硬链接。在克隆中更改文件时,将写入副本以代表新版本。
我发现这个在PHP约zval的好文章,里面提到过COW:
写时复制(缩写为“ COW”)是一种旨在节省内存的技巧。它在软件工程中更普遍地使用。这意味着,当您写入符号时,如果PHP已经指向zval,则PHP将复制该内存(或分配新的内存区域)。
以下是使用装饰器设计模式的写时复制(COW)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)