Linux の読み取り/書き込みシステム コールが、複数のスレッドまたはプロセスから単一ディスク ファイルの重複しない領域への非同期読み取り/書き込み (非追加書き込み) をサポートしているかどうかを知りたいです。各スレッドは、ファイルの独自の領域をシークし、この領域からのみ読み取り/書き込みを行い、他のスレッドが操作している領域と重複することはありません。
POSIX は XSH 2.9.7 で、実質的にすべての I/O 関数が、POSIX で指定された効果に関して相互にアトミックであることを指定しています。それが適用される特定の機能の長いリストが与えられ、 open()
、 lseek()
、 read()
、 write()
、および close()
すべてその上にあります。したがって、
2 つのスレッドがそれぞれこれらの関数の 1 つを呼び出す場合、各呼び出しは、他の呼び出しの指定された効果をすべて見るか、またはそれらのどれも見ないかのいずれかになります。
これは、開いている同じファイル記述に関連付けられたファイル記述子に対する操作であっても、外部同期に依存しません。
1 つのプロセス内であっても、同じファイルに対して複数のオープン ファイル記述が存在する場合があります (たとえば、open(2) のマニュアル ページを参照)。複数のスレッドが read()
を実行している場合 と write()
開いている異なるファイル記述を参照するファイル記述子を介して、同じ通常ファイルの重複しない領域に対する操作 、関連するスレッドの外部同期に関係なく、POSIXはこれらの操作が互いに干渉することを期待する根拠を提供しません。実際には、問題なく動作します。
トラブルに巻き込まれる場所 関連するスレッドが、開いている同じファイル記述を参照するファイル記述子を使用しようとしている場合です。これらは同じファイル記述子の値である必要はありません (したがって dup()
ファイル記述子を使用してもここでは役に立ちません)、状況が発生するためにスレッドが同じプロセスに属している必要もありません。開いている各ファイルの説明には 1 つの関連付けられたファイル位置があるため、2 つの異なるスレッドがそれぞれが 個別に必要とするタスクを実行しようとしている場合 ファイルオフセットを設定し、ファイルとの間でデータを転送し、それらが同じオープンファイル記述を使用している場合、個々の関数呼び出しの原子性は、読み取りと書き込みが意図した位置で実行されることを保証するには不十分です。そのシナリオでは同期が必要です。
あるいは、@ maximegorushkin がコメントで観察し、@ bk2204 が別の回答で観察したように、 pread()
そして pwrite()
関数は、1 回の呼び出しで位置決めとデータ転送を実行します。これらはアトミック I/O 関数のリストにもあり、データ転送ごとのデータ転送からの位置決めの分離を克服します。それらを使用するには特別な注意と簿記が必要であり、適切に機能しないシナリオもありますが、問題の特定のケースでは実行可能かもしれません.
だから 、2 つの異なるスレッドが同期せずに同じファイルを操作したい場合、最も安全で最も一般的な方法は、それぞれのファイルを個別に開くことです。 I/O 操作がファイルのばらばらな領域に制限されている限り、それらは互いに干渉しません。ファイルのオーバーラップ領域を操作することさえ問題外ではありませんが、これにより、より複雑な、アプリケーション固有の考慮事項が導入されます。
はい、可能です。 pread
と pwrite
関数を使用すると、ファイル オフセットを変更せずに、特定のオフセットでファイルの読み取りと書き込みを行うことができます。これらは、マルチスレッド プログラムで読み書きできるように特別に設計されています。
POSIX、pwrite
に違反していることに注意してください。 O_APPEND
で開かれたファイル記述子 常にファイルの最後に書き込みます。