ノンブロッキング モードのファイルのエンド オブ ファイルはどのように検出されますか?
5 に答える
少なくとも POSIX (Linux を含む) では、明らかな答えは、ノンブロッキングの通常のファイルが存在しないということです。通常のファイルは常にブロックされ、O_NONBLOCK は黙って無視されます。
同様に、poll()/select() など。は、データがページ キャッシュ内にあるかディスク上にあるかに関係なく、通常のファイルを指す fd が I/O の準備ができていることを常に通知します (主に読み取りに関連します)。
EDITそして、 O_NONBLOCK は通常のファイルではノーオペレーションであるため、この質問に対する別の回答とは反対に、通常のファイルの read() は決して errno を EAGAIN に設定しません。
EDIT2参照:
POSIX (p)select()仕様から: 「通常のファイルに関連付けられたファイル記述子は、読み取り可能、書き込み可能、およびエラー条件に対して常に true を選択する必要があります。」
POSIX poll()仕様から: 「通常のファイルは、読み取りと書き込みに対して常に TRUE をポーリングする必要があります。」
上記は、おそらく厳密に禁止されているわけではありませんが、ビジー待機以外にポーリングする方法がないため、非ブロッキングの通常のファイルは意味がないことを意味するのに十分です。
上記以外に、少なくともいくつかの状況証拠があります
POSIX open()仕様から: パイプ、ブロック特殊ファイル、および文字特殊ファイルを参照するファイル記述子の動作が定義されています。「それ以外の場合、O_NONBLOCK の動作は規定されていません。」
関連リンク:
http://tinyclouds.org/iocp-links.html
http://www.remlab.net/op/nonblock.shtml
http://davmac.org/davpage/linux/async-io.html
そして、ここでもstackoverflowで:
通常のファイル読み取りは、ノンブロッキング IO の恩恵を受けることができますか?
R. の回答が指摘しているように、ページ キャッシングの仕組みにより、通常のファイルのノンブロッキングは簡単には定義できません。たとえば、何らかのメカニズムによってページ キャッシュでデータを読み取る準備ができていることがわかり、それを読み取る前にカーネルがメモリ プレッシャーのためにそのページをキャッシュから追い出すことを決定した場合はどうなるでしょうか? ソケットやパイプなどの場合は異なります。正確さを保つには、データがそのように破棄されないことが必要だからです。
また、シーク可能なファイル記述子をどのように選択/ポーリングしますか? 関心のあるファイル内のバイト範囲の指定をサポートする新しい API が必要になります。また、関心のあるページを防止する必要があるため、その API のカーネル実装は VM システムに結び付けられます。追い出されることから。これは、DOS を防ぐために、これらのページがプロセス ロック ページ制限 (ulimit -l を参照) に対してカウントされることを意味します。そして、それらのページのロックが解除されるのはいつですか? 等々。
これは本当に良い質問です。非ブロッキング ソケットは、利用可能なデータがないことを示す をrecv()
スローするのではなく、空の文字列を返しsocket.error
ます。ただし、ファイルの場合、Python で使用できる直接的な指標はないようです。
EOF を検出するために私が考えることができる唯一のメカニズムは、空の文字列を受け取った後、ファイルの現在の位置を全体のファイル サイズと比較することです。
def read_nonblock( fd ):
t = os.read(fd, 4096)
if t == '':
if os.fstat(fd).st_size == os.lseek(fd, 0, os.SEEK_CUR):
raise Exception("EOF reached")
return t
もちろん、これは、非ブロッキング モードの通常のファイルが、ディスクからデータが読み取られるのを待つのではなく、実際にすぐに返されることを前提としています。それが Windows または Linux で正しいかどうかはわかりません。テストする価値はありますが、実際の EOF が発生したときに、非ブロック モードでも通常のファイルを読み取っても空の文字列しか返されない場合でも、私は驚かないでしょう。
C ++(YMMV)でうまく機能する優れたトリックは、返されるデータの量がバッファーのサイズより少ない場合(つまり、バッファーがいっぱいでない場合)、トランザクションが完了したと安全に想定できることです。その場合、ファイルの最後の部分がバッファを完全に満たす確率が1 /バッファサイズになるため、バッファサイズが大きい場合は、トランザクションが満たされていないバッファで終了することを合理的に確認できます。したがって、データの量をテストする場合バッファサイズに対して返され、それらが等しくない場合は、エラーが発生したか、トランザクションが完了したことがわかります。これがPythonに変換されるかどうかはわかりませんが、それがEOFを見つけるための私の方法です
選択すると、EOFだけでも読むべきものがあると言われませんか?読むべきものがあると表示され、何も返されない場合は、EOFである必要があります。これはソケットの場合だと思います。
ファイルの場合、ファイル記述子を非ブロッキングとして設定しても何も起こりません。とにかく、すべての IO がブロックされます。
ノンブロッキング ファイル IOが本当に必要な場合aio_read
は、ファイル アクセス用の非同期 IO 機能である友人を調べる必要があります。これらはかなり移植性が低く、動作が不安定な場合があります。そのため、ほとんどのプロジェクトでは、実際には IO に別のプロセス (またはスレッド) を使用し、そこでブロッキング IO を使用することにしました。
繰り返しになりますが、ファイルが大きくなったときに通知されるように、ファイルを「選択」することに興味があるかもしれません。おそらく気づいているようselect
に、poll
、 などは機能しません。ほとんどのソフトウェアは、1 秒ごとにファイルをポーリングするだけでこれを実行します。たとえば、"tail -f" はポーリングによって魔法のように実行します。ただし、ファイルが書き込まれたときにカーネルに通知させることもできます。これはinotify
友人によって行われます。これらすべてをまとめた便利なライブラリがいくつかあるので、自分で詳細をいじる必要はありません。つまり、python の場合、inotifyx
およびpyinotify
.