私はこれを実験で確認することができず、manページからも収集できませんでした。
2つのプロセスがあるとします。1つはfile1をdirectory1からdirectory2に移動(名前変更)します。同時に実行されている他のプロセスが、directory1とdirectory2の内容を別の場所にコピーするとします。コピーは、directory1とdirectory2の両方にfile1が表示されるような方法で行われる可能性があります。つまり、最初のプロセスによる移動の前にdirectory1が移動され、移動後にdirectory2がコピーされます。
基本的にrename()はアトミックシステムコールですか?
ありがとう
はいといいえ。
rename()は、OSがクラッシュしないことを前提としています。他のファイルシステム操作で分割することはできません。
システムがクラッシュすると、代わりにln()操作が表示される場合があります。
また、ネットワークファイルシステムで操作している場合、操作が成功するとENOENTが表示される場合があります。ローカルファイルシステムはあなたにそれをすることができません。
これは非常に遅い回答ですが...はいrename()
はアトミックですが、質問の意味ではありません。 Linuxでは、rename(2)
は次のように述べています。
ただし、上書きする場合、おそらくoldpathとnewpathの両方が名前を変更するファイルを参照するウィンドウが存在します。
しかし、rename()
は非常に重要な意味で依然としてアトミックです。それを使用してファイルを上書きすると、最終的には古いバージョンまたは新しいバージョンになり、それ以外のものはなくなります。
[pdate:ですが、@ jonas-wielickiがコメントで指摘しているように、fsync()
を使用して、名前を変更するファイルが実際に最新の内容であることを確認する必要があります友達。]
Newpathがすでに存在する場合は、アトミックに置き換えられます(いくつかの条件に従います。以下のエラーを参照してください)。そのため、newpathにアクセスしようとする別のプロセスがそれを見つけられなくなることはありません。
ERRORSが表示された場合、名前の変更は失敗する可能性がありますが、アトミック性が失われることはありません。
これはすべてLinuxのmanページにあります。サーバーが別のOSを実行しているネットワークファイルシステムでrename()
を実行するかどうかはわかりません。そのときクライアントは原子性を保証する地獄に希望を持っていますか?疑わしい。
質問の「基本的に」の部分が有効かどうかはわかりません。 2つの間に何らかの同期がない限り、アトミックな名前変更がどのように行われるかは問題ではありません。名前の変更前にディレクトリのコピーがそこに到着すると、両方の場所にfile1が存在することになります。
スレッドとプロセスのどちらを意味するのかはわかりませんが、両方にロックメカニズムがある場合、プロセスの境界を越える必要がないため、スレッドロックははるかに単純です。
gNU libc manual は言う
名前変更の便利な機能の1つは、newnameの意味が、以前に存在していたファイルからその名前で「原子的に」新しい意味に変更されることです(つまり、oldnameと呼ばれていたファイル)。 newnameが古い意味と新しい意味の「中間」に存在しない瞬間はありません。操作中にシステムクラッシュが発生した場合、両方の名前がまだ存在している可能性があります。ただし、newnameが存在する場合は、常にそのままになります。