5

通常のファイルへの書き込み/読み取りはノンブロッキングにできないようです。サポートについては、次のリファレンスを見つけました。

The Linux Programming Interface: A Linux and UNIX System Programming Handbook から:

"--- ノンブロッキング モードは、デバイス (端末や擬似端末など)、パイプ、FIFO、およびソケットで使用できます。(パイプとソケットのファイル記述子は open() を使用して取得されないため、fcntl を使用してこのフラグを有効にする必要があります。 () セクション 5.3 で説明されている F_SETFL 操作.) O_NONBLOCK は、セクション 13.1 で説明されているように、通常のファイルの I/O がブロックされないことをカーネル バッファー キャッシュが保証するため、通常、通常のファイルでは無視されます。強制的なファイルロックが採用されている場合のファイル (セクション 55.4) ---"

UNIX 環境での高度なプログラミング第 2 版から:

「--- ディスク ファイルの読み取りまたは書き込みが呼び出し元を一時的にブロックする可能性があるとしても、ディスク I/O に関連するシステム コールは遅いとは見なされないことも述べました。 ---」

http://www.remlab.net/op/nonblock.shtmlから:

「---通常のファイルは常に読み取り可能であり、常に書き込み可能です。これは、関連するPOSIX仕様に明確に記載されています。これを十分に強調することはできません。通常のファイルをノンブロッキングに配置しても、1ビットを変更する以外の影響はまったくありません.ファイル フラグ. 通常のファイルからの読み取りには時間がかかる場合があります. たとえば、ファイルがビジーなディスク上にある場合、I/O スケジューラに時間がかかりすぎて、ユーザーがアプリケーションがフリーズしていることに気付く場合があります. それにもかかわらず、非-blocking モードは機能しません。単純に機能しません。ファイルの読み取り可能性または書き込み可能性のチェックは、常にすぐに成功します。システムが I/O 操作を実行するのに時間が必要な場合は、タスクを読み取りから割り込み不可能なスリープ状態にします。またはシステムコールを書き込みます。 ---」

メモリが十分に利用可能な場合、読み取り/書き込みはカーネル バッファリングを介して実行されます。

私の質問は次のとおりです。カーネルがメモリ不足で、バッファリングがすぐに使用できないというシナリオはありますか? はいの場合、カーネルは何をしますか? 単純にエラーを返しますか、それとも素晴らしいトリックを実行しますか?

みんなありがとう!

4

1 に答える 1

0

O_NONBLOCK と引用テキストに関する私の見解:

  • O_NONBLOCK は、実際のディスク I/O をトリガーする syscall がブロックしたり、I/O が完了するのを待っていない場合、まったく効果がありません。O_NONBLCOK は、疑似ファイル (最初の引用で述べたように) やロックされたファイルへのアクセスなど、ファイルシステム レベルの操作にのみ影響します。O_NONBLOCK は、ブロック デバイス レベルでの操作には影響しません。

  • メモリ不足は O_NONBLOCK とは関係ありません。

  • O_NONBLOCK は、ロックされたファイルへのアクセスがブロックされるかどうかを決定します。たとえば、 flock() / lockf() を使用してファイルをロックできます。O_NONBLOCK が使用されている場合、read()/write() は、ブロックしてファイル ロックが解放されるのを待つ代わりに、EGAIN ですぐに戻ります。この同期の違いはファイルシステム レベルで実装されており、read()/write() システムコールが実際のディスク I/O をトリガーするかどうかとは関係がないことに注意してください。

  • 最初の引用の断片because the kernel buffer cache ensures that I/O on regular files does not blockは誤解を招くものであり、私はそれが間違っていると考えています。バッファリングにより、ファイルの読み取り/書き込みシステムコールがディスク I/O を引き起こし、ブロックする可能性が低くなるのは事実ですが、バッファリングだけでは I/O を完全に回避することはできません。ファイルがキャッシュされていない場合、カーネルはファイルから read() を実行するときに実際の IO を実行する必要があります。ファイルに write() を実行したときに、ページ キャッシュがダーティ ページでいっぱいになった場合、カーネルは最初に一部のデータをストレージ デバイスにフラッシュしてスペースを空ける必要があります。この断片を精神的に飛ばすと、テキストがより明確になると思います。

  • 2 番目の引用は一般的なようで (何かが遅いとはどういう意味ですか?)、I/O 関連の呼び出しが遅いと見なされない理由についての説明がありません。その周りのテキストには、著者が言おうとしたことをもう少し修飾する背景情報がもっとあるのではないかと思います.

  • カーネルのメモリ不足には、(a) バッファ キャッシュ内の空きページの不足と、(b) 新しいシステム コールを処理するための新しいデータ構造を割り当てるための十分なメモリがないという 2 つの形式があります。(a) の場合、カーネルはバッファ キャッシュ内のページを単純にリサイクルします。おそらく最初にダーティ ページをディスクに書き込みます。これは非常に一般的なシナリオです。(b) の場合、カーネルは、プログラム データをスワップ パーティションにページングするか、(これが失敗した場合) 既存のプロセスを強制終了することによって、メモリを解放する必要があります (OOM 関数が呼び出され、メモリ消費量が最も多いプロセスがほぼ強制終了されます)。 . これは一般的な操作モードではありませんが、システムはユーザー プロセスが強制終了された後も実行を続けます。

于 2015-08-04T11:54:41.817 に答える