質問
/tmp/foo
pathnameにディレクトリ以外のファイル(ファイル、名前付きパイプ/ソケットなど)があり、pathnameにディレクトリ以外のディレクトリがあるとします/tmp/bar
。その後、複数のプロセスが同時に実行を開始します。
プロセス1の機能は以下の通りである。
unlink('/tmp/foo') /* or rename('/tmp/foo', '/tmp/removed') */
unlink('/tmp/bar') /* or rename('/tmp/bar', '/tmp/removed') */
プロセス2等は以下の作業を行う。
link('/tmp/foo', '/tmp/bar')
私が理解しているように、プロセス2は成功できません。 (まだ存在している間に試しているlink(2)
場合でも存在するので失敗するか、消えて失敗しなければなりません。)/tmp/foo
/tmp/bar
EEXIST
/tmp/foo
ENOENT
unlink(2)
しかし、この直観は、および/またはシステムコールが切断効果の本質的に逐次的であるという前提に依存しているため、rename(2)
私の理解の検証を探しています。カーネルで2つのunlink(2)
AND / ORrename(2)
呼び出しが成功することを可能にする* nixに似たシステムはありますか?しかし、どちらも成功しています(プロセス呼び出しでANDを抽象化/非表示するのではなく、AND切断の順序をlink(2)
変更したり、他の奇妙な競合状態/バグを介して)?/tmp/foo
/tmp/bar
link(2)
現在の理解
私はLinuxといくつかのBSDの、、およびunlink(2)
マニュアルrename(2)
ページとこれらの機能のPOSIX仕様を読みました。link(2)
でも、とても考えてみると、そのテーマについて安心できる内容が全く入っていないようです。少なくともrename(2)
私たちは約束します目的地すでに存在する場合は原子的に置き換えられます(オペレーティングシステム自体の欠陥を取り除いて)、しかし他に何もありません。
私は見た主張する複数の同時実行は、rename(foo, qux)
1つの名前変更を除いて、すべて原子的に移植可能に失敗するので、ENOENT
希望があります!同じ状況でも失敗するように拡張できるかどうかはわかりませんlink(foo, bar)
。ENOENT
優先回答
私はこれが「否定的なものを証明できない」状況の1つであることを知っています。私たちができる最善は、link(2)
プロセス2が成功することを可能にする* nixのようなシステムがあるという証拠がないことに注意してください。
だから私が探しているのは、できるだけ多くの* nixシリーズシステム(少なくともLinux、OSシステム、そしてこの小さな範囲の問題(原子的/順序付けられたファイルシステムの作業))に対処する答えです。前述のMac OS Xのような問題について(可能な限り)知っていると確信しています。rename(2)
おなじみのプラットフォームに問題がある場合、実際には原子的なバグではありません。これにより、私が思うように動作し、信頼できるほど移植性が高いという確信があります。
最終メモ
これは「X/Y問題」の質問ではありません。さまざまなロック/IPCメカニズムや、これらの特定のシステムコールがどのようにやり取りするかについての不確実性を解決する他の方法を紹介することで、答えることができる根本的な質問はありません。上記のシステムコールを使用して、現在実際に使用されている* nixシリーズシステムで予想どおりに移植可能な対話を実行できるかどうかを知りたいです。
答え1
などの基準を見てください。POSIX携帯性を保証します。実際、ほとんどのPOSIX準拠システムは仕様からわずかに外れていますが、通常は仕様に記載されている保証を信頼できます。ほとんどの最新のユニスは、正式にテストされていなくてもこの仕様に準拠しています。 bash設定を使用したり、POSIXLY_CORRECT=1
Solarisで/usr/xpg4/bin
実行されていることを確認するなど、POSIXモードで実行する必要があるかもしれません/bin
。/usr/bin
PATH
シングルUnix v2(POSIXの以前の拡張)には、次のような言葉があります。link
:
この
link()
機能は、既存のファイルへの新しいリンクを自動的に生成し、ファイル内のリンクの数を1ずつ増やします。
~についてrename
:
リンク名がある場合新しいパラメータが存在する場合は削除されます。古い次に名前を変更する新しい。この場合、new というリンクは、名前変更操作全体で他のプロセスに引き続き表示され、以下で参照されます。新しいまたは古い手術開始前。
POSIX は、ターゲットが存在する場合、その置換がアトミックでなければならないことを明示的に指定します。しかし、名前変更自体がアトミックでなければならないとは明記していません。つまり、2 つが同時に発生する時点はありません。古いそして新しい問題のファイルを参照するか、両方が利用できない場合は参照してください。実際、これらの属性はUNIXシステム、少なくともローカルファイルシステムでは正確です。
また、作業順序が保証されます。 Cでは、;
順次実行が保証されます。 sh では、;
/newline が順次実行 (例えば do&&
など) を保証します。だから
unlink("/tmp/foo");
unlink("/tmp/bar");
/tmp/foo
存在していたが存在しなかった特定の時点がないことが保証されます/tmp/bar
(/tmp/bar
もともと存在していたと仮定)。したがって、同時プロセスの実行はlink("/tmp/foo", "/tmp/bar")
成功できません。
原子性は保証されません。弾力。原子性は、リアルタイムシステムで観察可能な動作に関する。ファイルシステムの文脈では、回復力はシステムがクラッシュしたときに発生する状況を表します。多くのファイルシステムはパフォーマンスのために弾力性を犠牲にしているため、実行が中断されるとunlink("foo"); unlink("bar");
(現在のディレクトリがディスクストアにある場合)、削除されたままになる可能性bar
がfoo
あります。
一部のネットワークファイルシステムは、他のクライアントでタスクが発生したときにより少ない保証を提供します。以前のNFS実装はこの問題で悪名高いです。現代の実装はより良いと思いますが、現代のNFSの経験はありません。