web-dev-qa-db-ja.com

fcntl、lockf、ファイルのロックに使用する方が良いですか?

両方の advantages および disadvantages に関する情報を探していますfcntl およびlockfはファイルのロック用です。たとえば、移植性のためにどちらを使用するのが良いですか?私は現在Linuxデーモンをコーディングしていますが、相互排除を強制するためにどちらが適しているのか疑問に思っています。

46
cweston

lockfとfcntlの違いは何ですか:

多くのシステムでは、lockf()ライブラリルーチンはfcntl()のラッパーにすぎません。つまり、lockffcntlが提供する機能のサブセットを提供します。

ソース

ただし、一部のシステムでは、fcntlおよびlockfロックは完全に独立しています。

ソース

実装に依存するため、常に同じ規則を使用するようにしてください。したがって、常に両方のプロセスからlockfを使用するか、常にfcntlを使用します。互換性がある可能性は十分ありますが、同じものを使用する方が安全です。

どちらを選択してもかまいません。


必須ロックとアドバイザリロックに関する注意事項:

Unix/linuxでのロックはデフォルトでadvisoryです。つまり、他のプロセスは設定されたロック規則に従う必要はありません。したがって、連携するプロセスも同じ規則を使用している限り、どの方法でロックしてもかまいません。

Linuxは必須ロックをサポートしていますが、ファイルシステムがオプションonでマウントされ、ファイルの特殊な属性が設定されている場合のみです。 mount -o mandを使用してファイルシステムをマウントし、ファイル属性g-x,g+sを設定して必須ロックを有効にしてから、fcntlまたはlockfを使用できます。強制ロックの仕組みの詳細については、 ここ を参照してください。

ロックは個々のファイルではなく、iノードに適用されることに注意してください。つまり、同じファイルデータを指す2つのファイル名は、同じロックステータスを共有します。

一方、Windowsでは、ファイルをアクティブに排他的に開くことができます。これにより、他のプロセスがファイルを完全に開くことができなくなります。彼らがしたい場合でも。つまり、ロックは必須です。 Windowsとファイルロックについても同様です。適切なアクセス権を持つ開いているファイルハンドルを持つプロセスは、ファイルの一部をロックでき、他のプロセスはその部分にアクセスできません。


Linuxでの必須ロックの動作:

強制ロックに関して、プロセスがファイルの領域を読み取りロックでロックした場合、他のプロセスは読み取りが許可されますが、その領域への書き込みは許可されません。プロセスがファイルの領域を書き込みロックでロックした場合、他のプロセスはファイルの読み取りまたは書き込みを許可されません。プロセスがファイルの一部へのアクセスを許可されていない場合に何が起こるかは、O_NONBLOCKを指定したかどうかによって異なります。ブロッキングが設定されている場合、操作の実行を待機します。ブロッキングが設定されていない場合、EAGAINのエラーコードが表示されます。


NFS警告:

NFSマウントでロックコマンドを使用する場合は注意してください。動作は未定義であり、実装はローカルロックのみを使用するか、リモートロックをサポートするかによって大きく異なります。

62
Brian R. Bondy

どちらのインターフェースもPOSIX標準の一部であり、現在、ほとんどのシステムで両方のインターフェースを使用できます(Linux、FreeBSD、Mac OS X、およびSolarisを確認したところです)。したがって、要件に合ったものを選択して使用してください。

注意点:1つのプロセスがfcntlを使用してファイルをロックし、別のプロセスがlockfを使用してファイルをロックした場合の動作は不定です。ほとんどのシステムではこれらは同等の操作です(実際にはLinuxのlockfはfcntlの上に実装されています)が、POSIXはそれらの相互作用は規定されていないと述べています。したがって、2つのインターフェースのいずれかを使用する別のプロセスと相互運用している場合は、同じインターフェースを選択します。

他の人は、ロックは単なる助言であると書いています:リージョンがロックされているかどうかをチェックするのはあなたの責任です。また、ロック機能を使用する場合は、stdio関数を使用しないでください。

10

この場合の主な懸念事項(つまり、「Linuxデーモンのコーディング時」と、どちらがより適しているか相互排除を強制する場合 ")は、次のようになります。

  1. ロックされたファイルはローカルですか、それともNFS上にありますか?
    • 例えばユーザーはあなたをだましてNFSでデーモンのpidファイルを作成してロックさせることができますか?
  2. forking、またはデーモンプロセスが極端な偏見で終了した場合、ロックはどのように動作しますか。 kill -9

flockコマンドとfcntlコマンドは、どちらの場合でも動作が異なります。

私の推奨は、fcntlを使用することです。両方のソリューションに関連する問題の詳細については、 Wikipediaのファイルロックに関する記事 を参照してください。

Flockとfcntlには、他のオペレーティングシステムからプログラマーを時々困惑させるような癖があります。フロックロックがNFSなどのネットワークファイルシステムで機能するかどうかは、実装によって異なります。 BSDシステムでは、flock呼び出しは正常に動作しません。 2.6.12より前のLinuxでは、NFSファイルに対するflock呼び出しはローカルでのみ機能しました。カーネル2.6.12以降では、POSIXバイト範囲ロックを使用してNFSファイルにflock呼び出しを実装しています。これらのロックは、fcntl()/ POSIXロックを実装する他のNFSクライアントに表示されます。 1 ロックのアップグレードとダウングレードは、新しいロックを適用する前に古いロックを解放します。アプリケーションが排他ロックを共有ロックにダウングレードするときに、別のアプリケーションが排他ロックを待機してブロックされている場合、後者のアプリケーションが排他ロックを取得し、最初のアプリケーションがロックアウトされます。特定のプロセスのファイルに関連付けられているすべてのfcntlロックは、そのファイル記述子のロックが要求されたことがない場合でも、そのファイルのファイル記述子がそのプロセスによって閉じられると削除されます。また、fcntlロックは子プロセスに継承されません。 fcntlクローズセマンティクスは、ファイルにアクセスする可能性のあるサブルーチンライブラリを呼び出すアプリケーションにとって特に厄介です。

9
vladr

最近、fcntlとflockを使用しているときに問題を見つけました。どちらかの用語を検索すると、このページの両方の上部に表示されるため、ここで報告する必要があると感じました。

上記のように、BSDロックはadvisoryです。 OSX(darwin)を知らない人はBSDです。これは、書き込むファイルを開くときに覚えておく必要があります。

Fcntl/flockを使用するには、最初にファイルを開いてそのIDを取得する必要があります。ただし、 "w"でファイルを開いた場合、ファイルは即座にzeroed outになります。ファイルが他の場所で使用されているためにプロセスがロックの取得に失敗した場合、ファイルは0kbのままにして戻る可能性が高くなります。ロックされたプロセスは、ファイルがその下から消えたことを検出します。通常、破滅的な結果が続きます。

この状況を改善するには、ファイルロックを使用するときにneverでファイル "w"を開きますが、代わりに "a"で開きます。その後、ロックが正常に取得された場合は、「w」と同じようにファイルを安全にクリアできます。 :

fseek(fileHandle、0、SEEK_SET); //最初に移動

ftruncate(fileno((FILE *)fileHandle)、0); //クリアする

これは私にとって不愉快な教訓でした。

7
RMCE

あなたは相互排除のためにそれを使用するデーモンをコーディングしているだけなので、それらは同等です、結局のところ、あなたのアプリケーションはそれ自身と互換性があれば十分です。

ファイルロックメカニズムの秘訣は、一貫性を保つことです。それらを変化させることは悪い考えです。

ここではファイルシステムがローカルであると想定しています-そうでない場合、すべての賭けはオフになり、NFS /他のネットワークファイルシステムはさまざまな程度の効果でロックを処理します(場合によってはなし)

1
MarkR