コピーオンライト

From Wikipedia, the free encyclopedia

コピーオンライト: Copy-On-Write、略称: COW / CoW)とは、コンピュータにおいてデータ複製の実行を、実際の書き込み要求が発生するまで遅延させるリソース管理技法である。

具体的には、データ複製を要求された際、物理的なコピーを即座に実行せず、複数の要求者に同一リソースを共有参照させる。いずれかの要求者が変更(書き込み)を試みた時点で初めて、複製を生成する。

変更が生じない限り複製のコスト(処理時間とメモリ消費)が発生しない点に特徴がある。これにより、読み取り主体の処理においてリソースを節約し、実行速度を向上させることが可能となる。

仮想記憶への応用

コピーオンライトは主に仮想記憶方式のオペレーティングシステム (OS) で使用されている。 例えば、プロセスのコピーを作成 (fork) するとき、書き換えることのないメモリページは、両方のプロセス(元のプロセスと生成されたプロセス)で共用し、書き換える可能性のあるメモリページは、新たなメモリページを割り当ててコピーを作成する必要がある。 ここでコピーオンライトが使用される。一方のプロセスがメモリを更新すると、OSのカーネルがその操作を横取りし、メモリのコピーを作成してメモリ内容の更新が他方のプロセスから見えないようにする。

他にも、標準Cライブラリcalloc()関数の実装に使われることがある。calloc()はメモリ領域をゼロで初期化して確保する(malloc参照)。愚直な実装であればmalloc()で確保した領域に対してmemset()を呼び出すだけになるであろう。しかし最適化された実装では、ゼロで初期化されたページをシステムに1つ用意しておき、calloc()で確保した領域にはこのページをマッピングしてコピーオンライト機能を使用する[1][2]。このようにするとcalloc()呼び出し直後はたとえ何ページのメモリが必要でも物理的には1ページしか使われておらず、その領域の内容を更新しようとしたときに初めて個別のコピーが作成される。このような最適化はページサイズ以上の大きなアロケーションでのみ使用されるのが一般的である。

コピーオンライトは、MMUに対してプロセスのアドレス空間のある領域がリードオンリーであると通知することで実現する。その領域にデータを書き込もうとしたとき、MMUは例外を発生し、それをカーネルが処理する。カーネルは新たな物理ページを確保して、書き込みが行われた領域のマッピングを変更して、その新たな物理ページに対応させる。

COWの主な利点は、メモリを空間的にまばらに利用する可能性にある。データを格納したときだけ物理メモリ使用量が増えるので、若干メモリ使用量が増えるが非常に効率的なハッシュテーブルを実装することができる。しかし、そのような使い方をすると仮想空間を使い切ってしまう危険性もある(ハッシュテーブルに使われる仮想アドレス空間の領域はマッピングされる物理ページはまばらだが、他の用途に空間を利用できない)。カーネルレベルでのCOWの主な問題点はその複雑さにあるが、そのような懸念はスワップ方式などのもっと基本的な部分も同じである。カーネル自身がコピーオンライト制御されているページに書き込みを行った場合、やはりコピーが必要となる(訳注:例えばシステムコールの結果をユーザー空間に書き込む場合など。実際には書きこみの前にコピーオンライトかどうかをチェックし、必要に応じてコピー作成後に書き込みを行う)。

COWはカーネル以外でも、ライブラリアプリケーションやシステムコードなどでも使われる。C++Standard Template Libraryが提供するstd::stringクラスは、かつてISO/IEC 14882:2003(通称C++03)規格まではコピーオンライト型の実装が可能な設計(外部仕様)になっていた[注釈 1]。しかし、このような領域でのCOWはマルチスレッドコードで問題となる。コピー元のリソースを複数のスレッドで共有するにはロックが必要であり、COWの利点以上のオーバーヘッドとなる可能性が高い。

ファイルシステムへの応用

COWはファイルシステムにおけるスナップショット機能を実現するアルゴリズムとして利用される。特定時点のファイルシステムの状態を原本とし、その後ファイルまたはブロックの変更があった場合には新たにオリジナルのそれをコピーし、変更をそのコピーにのみ反映することで実現する。スナップショット機能を備える論理ボリュームマネージャやファイルシステムの多くがその実現にCOWを用いている。

単純なファイルのコピーも、COWで効率化できる可能性がある。ただし、ファイルシステムでのサポートとOSがファイルコピー用のAPIを提供し、アプリケーションがそれを使用することが条件となる。macOSiOSといったAppleのプラットフォームで、HFS+の後継として採用されているApple File System (APFS) は、COWをサポートしており、単純なファイルコピー自体は一瞬で終わるようになっている[3][4]WindowsWindows NT系)で従来から使われてきたNTFSはCOWをサポートしていないが、Resilient File System (ReFS) はCOWをサポートしており、Windows 11のバージョン22H2以降は開発ドライブ(Dev Drive)という機能と対応APIによってファイルのCOWが利用できるようになっている[5]。さらにWindows 11のプレビュー版では従来のWindows APIであるCopyFile()関数でも対応環境上であればCOWが利用できるようになるアーリーアクセスが提供されている[6]。なお、POSIXにはそういったファイルシステムレベルのサポートやシステムコールは存在しない。

ファイルシステムが重複排除機構を備えている場合は更に相性が良い。前述の通り、COWにてコピーされたファイルは元ファイルと同一のデータブロックを参照しているため、コピー終了時点で「重複排除済み」とみなすことができる。このためCOWコピーされたファイルに改めて重複排除処理を加える必要がなくなる(もしくは一瞬で完了する)。

また、BochsQEMUといった仮想マシンの仮想ディスク装置で使われている。同じディスクイメージを使って複数の仮想マシンを動作させれば、必要とされるディスク容量を劇的に減らすことができる。またディスクからの読み込みイメージがメモリにキャッシュされ、それが仮想マシン間で共有されるため、性能も向上する。

制限事項として、ファイル上の既存のデータを更新する場合、コピーオンライト処理のために一定の空き容量が必要となる。データ更新の処理中、一時的に更新前と後のデータの両方がファイルシステムに存在することに依る。コピーオンライト処理のために十分な空き領域がファイルシステムにない場合は、ファイルシステムに空き容量があるにもかかわらず容量不足のエラーが発生し、一見奇妙な問題となる。

脚注

関連項目

Related Articles

Wikiwand AI