Copy on write windows
Copy on Write or simply COW is a resource management technique. One of its main use is in the implementation of the fork system call in which it shares the virtual memory(pages) of the OS.
In UNIX like OS, fork() system call creates a duplicate process of the parent process which is called as the child process.
The idea behind a copy-on-write is that when a parent process creates a child process then both of these processes initially will share the same pages in memory and these shared pages will be marked as copy-on-write which means that if any of these processes will try to modify the shared pages then only a copy of these pages will be created and the modifications will be done on the copy of pages by that process and thus not affecting the other process.
Suppose, there is a process P that creates a new process Q and then process P modifies page 3.
The below figures shows what happens before and after process P modifies page 3.
Attention reader! Don’t stop learning now. Get hold of all the important CS Theory concepts for SDE interviews with the CS Theory Course at a student-friendly price and become industry ready.
Копирование при записи — Copy-on-write
Копирование при записи ( COW ), иногда называемое неявным совместным использованием или теневым копированием , представляет собой метод управления ресурсами, используемый в компьютерном программировании для эффективной реализации операции «дублирования» или «копирования» на изменяемых ресурсах. Если ресурс дублируется, но не изменяется, нет необходимости создавать новый ресурс; ресурс может быть разделен между копией и оригиналом. Модификации все равно должны создавать копию, отсюда и техника: операция копирования откладывается до первой записи. Совместное использование ресурсов таким образом позволяет значительно снизить потребление ресурсов немодифицированными копиями, добавляя при этом небольшие накладные расходы на операции изменения ресурсов.
СОДЕРЖАНИЕ
В управлении виртуальной памятью
Копирование при записи находит свое основное применение в обмене виртуальной памяти в операционных системах процессов , в реализации системы вилки вызова . Обычно процесс не изменяет память и немедленно выполняет новый процесс, полностью заменяя адресное пространство. Таким образом, было бы расточительно копировать всю память процесса во время вилки, и вместо этого используется техника копирования при записи.
Копирование при записи может быть эффективно реализовано с использованием таблицы страниц , помечая определенные страницы памяти как доступные только для чтения и ведя подсчет количества ссылок на страницу. Когда данные записываются на эти страницы, ядро перехватывает попытку записи и выделяет новую физическую страницу, инициализированную данными копирования при записи, хотя выделение можно пропустить, если имеется только одна ссылка. Затем ядро обновляет таблицу страниц новой (доступной для записи) страницей, уменьшает количество ссылок и выполняет запись. Новое распределение гарантирует, что изменение в памяти одного процесса не будет видно в памяти другого.
Методика копирования при записи может быть расширена для поддержки эффективного распределения памяти за счет заполнения страницы физической памяти нулями. Когда память выделена, все возвращенные страницы ссылаются на страницу нулей и помечаются как копирование при записи. Таким образом, физическая память не выделяется для процесса до тех пор, пока данные не будут записаны, что позволяет процессам резервировать больше виртуальной памяти, чем физическая память, и использовать память редко, рискуя исчерпать виртуальное адресное пространство. Комбинированный алгоритм аналогичен пейджингу по запросу .
Копирование при записи страница также используется в Linux ядро «s ядро же страницы слияния функций.
Загрузка библиотек для приложения также является использованием техники копирования при записи. Динамический компоновщик отображает библиотеки как частные, как показано ниже. Любое действие записи в библиотеки вызовет COW в управлении виртуальной памятью.
В программном обеспечении
COW также используется в коде библиотеки , приложения и системы .
В многопоточных системах COW можно реализовать без использования традиционной блокировки и вместо этого использовать функцию сравнения и замены для увеличения или уменьшения внутреннего счетчика ссылок. Поскольку исходный ресурс никогда не будет изменен, его можно безопасно скопировать несколькими потоками (после увеличения счетчика ссылок) без необходимости дорогостоящей блокировки, такой как мьютексы . Если счетчик ссылок становится равным 0, то по определению только 1 поток содержал ссылку, поэтому ресурс можно безопасно освободить от памяти, опять же без использования дорогостоящих механизмов блокировки. Таким образом, преимущество отсутствия копирования ресурса (и, как следствие, повышение производительности по сравнению с традиционным глубоким копированием) будет справедливо как в однопоточных, так и в многопоточных системах.
Примеры
Строка класса предусмотрено C ++ стандартная библиотека была специально разработана , чтобы позволить копирования при записи реализации в начальной C ++ 98 стандарта, но не в новой C ++ 11 стандарт:
В языке программирования PHP все типы, кроме ссылок, реализованы как копирование при записи. Например, строки и массивы передаются по ссылке, но при изменении они дублируются, если имеют ненулевое количество ссылок. Это позволяет им действовать как типы значений без проблем с производительностью, связанных с копированием при назначении или их неизменяемостью.
В структуре Qt многие типы копируются при записи («неявно разделяются» в терминах Qt). Qt использует атомарные операции сравнения и замены для увеличения или уменьшения внутреннего счетчика ссылок. Поскольку копии дешевы, типы Qt часто могут безопасно использоваться несколькими потоками без необходимости использования механизмов блокировки, таких как мьютексы . Таким образом, преимущества COW проявляются как в однопоточных, так и в многопоточных системах.
В хранилище компьютера
COW также может использоваться в качестве основного механизма для моментальных снимков , например, предоставляемых управлением логическими томами , файловыми системами, такими как Btrfs и ZFS , и серверами баз данных, такими как Microsoft SQL Server . Обычно моментальные снимки хранят только измененные данные и хранятся рядом с основным массивом, поэтому они являются лишь слабой формой инкрементного резервного копирования и не могут заменить полную резервную копию . Некоторые системы также используют метод COW, чтобы избежать нечетких резервных копий , которые в противном случае возникают, когда какой-либо файл в наборе файлов, для которых выполняется резервное копирование, изменяется во время этого резервного копирования.
При создании снимков используются два метода:
- Перенаправление при записи или ROW: исходное хранилище никогда не изменяется. Когда делается запрос на запись, он перенаправляется от исходных данных в новую область хранения.
- Копирование при записи или COW: когда делается запрос на запись, данные копируются в новую область хранения, а затем исходные данные изменяются.
Несмотря на их названия, копирование при записи обычно относится к первой технике. COW выполняет две записи данных по сравнению с записью ROW; его сложно реализовать эффективно, и поэтому он используется нечасто.
Технику копирования при записи можно использовать для имитации хранилища для чтения и записи на носителях, которые требуют выравнивания износа или физически записывают один раз, много читают .
Формат образа диска qcow2 (копия QEMU при записи) использует технику копирования при записи для уменьшения размера образа диска.
Некоторые live CD (и live USB ) используют методы копирования при записи, чтобы создать впечатление, что можно добавлять и удалять файлы в любом каталоге, не внося никаких изменений в CD (или USB-накопитель).
В высоконадежном программном обеспечении
Phantom OS использует COW на всех уровнях, а не только в базе данных или файловой системе. В любой момент компьютер с этой системой может выйти из строя, а затем, когда он снова запустится, программное обеспечение и операционная система возобновят работу. Может быть потеряно только небольшое количество работы.
Основной подход заключается в том, что все данные программы хранятся в виртуальной памяти. По некоторому расписанию сводка всех данных программного обеспечения записывается в виртуальную память, образуя журнал, в котором отслеживается текущее значение и расположение каждого значения.
Когда компьютер выходит из строя, последняя копия журнала и другие данные остаются в безопасности на диске. Когда работа возобновляется, программное обеспечение операционной системы считывает журнал для восстановления согласованных копий всех программ и данных.
Этот подход использует копирование при записи на всех уровнях всего программного обеспечения, включая прикладное программное обеспечение. Для этого требуется поддержка в рамках языка программирования приложений. На практике Phantom OS разрешает только языки, генерирующие байт-код Java .
Copy-on-write file mapping on windows
I have 3 processes communicating over named pipes: server, writer, reader. The basic idea is that the writer can store huge (
GB) binary blobs on the server, and the reader(s) can retrieve it. But instead of sending data on the named pipe, memory mapping is used.
The server creates an unnamed file-backed mapping with CreateFileMapping with PAGE_READWRITE protection, then duplicates the handle into the writer. After the writer has done its job, the handle is duplicated into any number of interested readers.
The writer maps the handle with MapViewOfFile in FILE_MAP_WRITE mode.
The reader maps the handle with MapViewOfFile in FILE_MAP_READ|FILE_MAP_COPY mode.
On the reader I want copy-on-write semantics, so as long the mapping is only read it is shared between all reader instances. But if a reader wants to write into it (eg. in-place parsing or image processing), the impacts should be limited to the modifying process with the least number of copied pages possible.
The problem
When the reader tries to write into the mapping it dies with segmentation fault as if FILE_MAP_COPY was not considered. What’s wrong with the above described method? According to MSDN this should work.
We have the same mechanism implemented on linux as well (with mmap and fd passing in AF_UNIX ancillary buffers) and it works as expected.
What is copy-on-write?
I would like to know what copy-on-write is and what it is used for. The term is mentioned several times in the Sun JDK tutorials.
9 Answers 9
I was going to write up my own explanation but this Wikipedia article pretty much sums it up.
Here is the basic concept:
Copy-on-write (sometimes referred to as «COW») is an optimization strategy used in computer programming. The fundamental idea is that if multiple callers ask for resources which are initially indistinguishable, you can give them pointers to the same resource. This function can be maintained until a caller tries to modify its «copy» of the resource, at which point a true private copy is created to prevent the changes becoming visible to everyone else. All of this happens transparently to the callers. The primary advantage is that if a caller never makes any modifications, no private copy need ever be created.
Also here is an application of a common use of COW:
The COW concept is also used in maintenance of instant snapshot on database servers like Microsoft SQL Server 2005. Instant snapshots preserve a static view of a database by storing a pre-modification copy of data when underlaying data are updated. Instant snapshots are used for testing uses or moment-dependent reports and should not be used to replace backups.
«Copy on write» means more or less what it sounds like: everyone has a single shared copy of the same data until it’s written, and then a copy is made. Usually, copy-on-write is used to resolve concurrency sorts of problems. In ZFS, for example, data blocks on disk are allocated copy-on-write; as long as there are no changes, you keep the original blocks; a change changed only the affected blocks. This means the minimum number of new blocks are allocated.
These changes are also usually implemented to be transactional, ie, they have the ACID properties. This eliminates some concurrency issues, because then you’re guaranteed that all updates are atomic.
I shall not repeat the same answer on Copy-on-Write. I think Andrew’s answer and Charlie’s answer have already made it very clear. I will give you an example from OS world, just to mention how widely this concept is used.
We can use fork() or vfork() to create a new process. vfork follows the concept of copy-on-write. For example, the child process created by vfork will share the data and code segment with the parent process. This speeds up the forking time. It is expected to use vfork if you are performing exec followed by vfork. So vfork will create the child process which will share data and code segment with its parent but when we call exec, it will load up the image of a new executable in the address space of the child process.
Just to provide another example, Mercurial uses copy-on-write to make cloning local repositories a really «cheap» operation.
The principle is the same as the other examples, except that you’re talking about physical files instead of objects in memory. Initially, a clone is not a duplicate but a hard link to the original. As you change files in the clone, copies are written to represent the new version.
The book Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma et al. clearly describes the copy-on-write optimization (section ‘Consequences’, chapter ‘Proxy’):
The Proxy pattern introduces a level of indirection when accessing an object. The additional indirection has many uses, depending on the kind of proxy:
- A remote proxy can hide the fact that an object resides in a different address space.
- A virtual proxy can perform optimizations such as creating an object on demand.
- Both protection proxies and smart references allow additional housekeeping tasks when an object is accessed.
There’s another optimization that the Proxy pattern can hide from the client. It’s called copy-on-write, and it’s related to creation on demand. Copying a large and complicated object can be an expensive operation. If the copy is never modified, then there’s no need to incur this cost. By using a proxy to postpone the copying process, we ensure that we pay the price of copying the object only if it’s modified.
To make copy-on-write work, the subject must be referenced counted. Copying the proxy will do nothing more than increment this reference count. Only when the client requests an operation that modifies the subject does the proxy actually copy it. In that case the proxy must also decrement the subject’s reference count. When the reference count goes to zero, the subject gets deleted.
Copy-on-write can reduce the cost of copying heavyweight subjects significantly.
Here after is a Python implementation of the copy-on-write optimization using the Proxy pattern. The intent of this design pattern is to provide a surrogate for another object to control access to it.
Class diagram of the Proxy pattern:
Object diagram of the Proxy pattern:
First we define the interface of the subject:
Next we define the real subject implementing the subject interface:
Finally we define the proxy implementing the subject interface and referencing the real subject:
The client can then benefit from the copy-on-write optimization by using the proxy as a stand-in for the real subject: