56

O_SYNC および O_DIRECT フラグの使用と効果は非常に紛らわしく、プラットフォームによって多少異なるようです。Linux のマニュアル ページ (こちらの例を参照) によると、O_DIRECT は同期 I/O を提供し、キャッシュの影響を最小限に抑え、ブロック サイズのアライメントを自分で処理する必要があります。O_SYNC は、同期 I/O を保証するだけです。どちらもデータがハードディスクのキャッシュに書き込まれることを保証しますが、直接の I/O 操作は、ページ キャッシュをバイパスするため、単純な同期 I/O よりも高速であると思われます (Open(2) の FreeBSD のマニュアル ページには、 O_SYNC が使用されている場合、キャッシュはバイパスされます (こちらを参照)。

O_DIRECT フラグと O_SYNC フラグの違いは何ですか? 一部の実装では、O_SYNC | の使用が推奨されています。O_DIRECT。なんで?

4

4 に答える 4

105

O_DIRECT だけでは、カーネルがユーザー空間からカーネル空間にデータをコピーすることを回避し、代わりに DMA (可能であれば直接メモリ アクセス) を介して直接書き込むことを約束するだけです。データはキャッシュに入りません。すべてのデータが転送された後にのみ関数が戻るという厳密な保証はありません。

O_SYNC は、すべてのデータがディスクに転送される前に呼び出しが戻らないことを保証します(OS が判断できる限り)。これは、データがハードディスクの書き込みキャッシュのどこかにないことを保証するものではありませんが、OS が保証できる限りのことです。

O_DIRECT|O_SYNC はこれらの組み合わせ、つまり「DMA + 保証」です。

于 2011-03-22T11:00:08.080 に答える
17

O_DIRECT と O_SYNC の役割とデータの整合性への影響の明確な説明については、この lwn 記事を参照してください。

https://lwn.net/Articles/457667/

于 2016-05-24T14:27:06.157 に答える
9

実際、Linux 2.6 では、o_direct は同期です。man ページを参照してください。

オープンのマンページには、それに関する2つのセクションがあります..

2.4未満では保証されていません

O_DIRECT (Linux 2.4.10 以降) このファイルとの間の I/O のキャッシュ効果を最小限に抑えようとします。一般に、これはパフォーマンスを低下させますが、アプリケーションが独自のキャッシュを行う場合など、特別な状況では役立ちます。ファイル I/O は、ユーザー空間バッファーとの間で直接行われます。O_DIRECT フラグは、単独でデータを同期的に転送しようとしますが、データと必要なメタデータが転送されることを O_SYNC フラグで保証するものではありません。同期 I/O を保証するには、O_DIRECT に加えて O_SYNC を使用する必要があります。詳細については、以下の注を参照してください。

ブロックデバイス用の意味的に似た (しかし非推奨の) インタフェースは raw(8) で説明されています。

ただし、2.6 未満では保証されています。

O_DIRECT

O_DIRECT フラグは、ユーザー空間バッファーの長さとアドレス、および I/O のファイル オフセットにアラインメント制限を課す場合があります。Linux では、アラインメントの制限はファイル システムとカーネルのバージョンによって異なり、完全に存在しない場合があります。ただし、現在、アプリケーションが特定のファイルまたはファイル システムのこれらの制限を検出するための、ファイル システムに依存しないインターフェイスはありません。xfsctl(3) の XFS_IOC_DIOINFO 操作のように、一部のファイル システムはそれを行うための独自のインターフェースを提供します。

Linux 2.4 では、転送サイズ、ユーザー バッファーのアラインメント、およびファイル オフセットはすべて、ファイル システムの論理ブロック サイズの倍数でなければなりません。Linux 2.6 では、512 バイト境界へのアライメントで十分です。

O_DIRECT I/O は、メモリ バッファがプライベート マッピング (つまり、mmap(2) MAP_PRIVATE フラグで作成された任意のマッピング) である場合、fork(2) システム コールと同時に実行してはなりません。これには、ヒープ上および静的に割り当てられたメモリが含まれます。割り当てられたバッファ)。そのような I/O は、非同期 I/O インターフェースを介して送信された場合でも、プロセス内の別のスレッドから送信された場合でも、fork(2) が呼び出される前に完了する必要があります。そうしないと、データが破損し、親プロセスと子プロセスで未定義の動作が発生する可能性があります。この制限は、O_DIRECT I/O のメモリ バッファが MAP_SHARED フラグを指定して shmat(2) または mmap(2) を使用して作成された場合には適用されません。また、この制限は、メモリ バッファが madvise(2) で MADV_DONTFORK としてアドバイスされている場合にも適用されず、fork(2) の後に子プロセスが利用できないことを保証します。

O_DIRECT フラグは SGI IRIX で導入されました。このフラグには、Linux 2.4 と同様のアラインメント制限があります。IRIX には、適切なアラインメントとサイズを照会するための fcntl(2) 呼び出しもあります。FreeBSD 4.x では、同じ名前のフラグが導入されましたが、アラインメントの制限はありません。

O_DIRECT のサポートは、Linux のカーネル バージョン 2.4.10 で追加されました。古い Linux カーネルは、このフラグを単純に無視します。一部のファイル システムはフラグを実装していない可能性があり、open() を使用すると EINVAL で失敗します。

アプリケーションは、O_DIRECT と通常の I/O を同じファイルに混在させないようにする必要があります。特に、同じファイル内でバイト領域がオーバーラップする場合は注意が必要です。ファイル システムがこの状況でコヒーレンシの問題を正しく処理したとしても、全体的な I/O スループットは、いずれかのモードを単独で使用するより遅くなる可能性があります。同様に、アプリケーションは、ファイルの mmap(2) と同じファイルへの直接 I/O を混在させないようにする必要があります。

NFS での O_DIRECT の動作は、ローカル ファイル システムとは異なります。古いカーネル、または特定の方法で構成されたカーネルは、この組み合わせをサポートしない場合があります。NFS プロトコルはサーバーへのフラグの受け渡しをサポートしていないため、O_DIRECT I/O はクライアントのページ キャッシュのみをバイパスします。サーバーは引き続き I/O をキャッシュする可能性があります。クライアントは、O_DIRECT の同期セマンティクスを維持するために、I/O を同期にするようサーバーに要求します。一部のサーバーは、特に I/O サイズが小さい場合、これらの状況下でパフォーマンスが低下します。一部のサーバーは、I/O が安定したストレージに到達したことについてクライアントに嘘をつくように構成されている場合もあります。これにより、サーバーの電源障害が発生した場合にデータの整合性が損なわれる可能性があるため、パフォーマンスの低下を回避できます。Linux NFS クライアントは、O_DIRECT I/O にアラインメントの制限を設けません。

要約すると、O_DIRECT は潜在的に強力なツールであり、注意して使用する必要があります。アプリケーションが O_DIRECT の使用をデフォルトで無効になっているパフォーマンス オプションとして扱うことをお勧めします。

「O_DIRECT についていつも私を悩ませているのは、インターフェイス全体が馬鹿げているということです。おそらく、精神をコントロールする深刻な物質について、狂った猿によって設計されたのでしょう。」---Linus

于 2013-04-28T03:32:35.910 に答える
1

私の知る限り、O_DIRECT はページ キャッシュをバイパスします。O_SYNC はページ キャッシュを使用しますが、すぐに同期します。ページ キャッシュはプロセス間で共有されるため、O_DIRECT フラグのない同じファイルで作業している別のプロセスがある場合、正しいデータを読み取ることができます。

于 2011-03-22T10:24:14.393 に答える