7

パイプのサイズを返す関数が必要ですSizeOfPipe()。パイプ内のデータ量を知りたいだけで、実際にパイプ自体からデータを読み取る必要はありません。

次のコードが機能すると思いました。

fseek (pPipe, 0 , SEEK_END);
*pBytes = ftell (pPipe);
rewind (pPipe);

ただしfseek()、ファイル記述子では機能しません。別のオプションは、パイプを読み取ってからデータを書き戻すことですが、可能であればこれを避けたいと考えています。助言がありますか?

4

13 に答える 13

18

UNIX の実装によっては、ioctl/FIONREAD でうまくいく場合があります。

err = ioctl(pipedesc, FIONREAD, &bytesAvailable);

これが「無効な引数」(またはその他のエラー) のエラー コードを返さない限り、bytesAvailable には、その時点で読み取り操作のブロックを解除するために使用できるデータの量が含まれています。

于 2008-09-16T13:10:04.990 に答える
6

st_size一部のUNIX実装は、呼び出し後にフィールドで読み取ることができるバイト数を返しますfstat()が、これは移植性がありません。

于 2008-09-16T12:59:17.713 に答える
4

残念ながら、システムはパイプのサイズを常に認識できるとは限りません。たとえば、長時間実行されるプロセスを別のコマンドにパイプする場合、ソース プロセスがまだ実行を終了していない可能性があります。この場合、そこからどれだけ多くのデータが得られるかを (理論的にも) 知る方法はありません。

現在パイプから読み取ることができるデータの量を知りたい場合は、可能かもしれませんが、OS のバッファリングや制御が難しいその他の要因に依存します。ここでの最も一般的なアプローチは、何も残らなくなるまで読み続けることです (EOF を取得しない場合、ソース プロセスはまだ終了していません)。しかし、これはあなたが探しているものではないと思います。

したがって、一般的な解決策はないと思います。

于 2008-09-16T12:53:09.757 に答える
2

一般に、パイプ ハンドルだけからパイプから読み取ることができるデータの量を知ることはできません。データは、ネットワーク経由で受信されるか、別のプロセスによって動的に生成されます。前もって知る必要がある場合は、パイプの反対側にあるプロセスによって、パイプを介して、または帯域外で、情報が送信されるように手配する必要があります。

于 2008-09-16T12:52:50.570 に答える
2

パイプを読み取らずに、パイプで使用可能なデータの量を知るための一般的で移植可能な方法はありません。少なくとも POSIX 仕様ではありません。

パイプはシークできず、データをパイプの読み取り側に戻すこともできません。

ただし、プラットフォーム固有のトリックは可能かもしれません。質問がプラットフォーム固有のものである場合は、質問を編集してそうすると、有効な回答が得られる可能性が高くなる可能性があります。

于 2008-09-16T12:52:58.913 に答える
2

パイプ内のバイト数を知る必要はほとんどありません。パイプに対してノンブロッキングの read() を実行したいだけかもしれません。準備ができているバイトがあるかどうかを確認し、ある場合はそれらを読み取りますが、パイプの準備が整うまで停止して待機することはありません。

2 つのステップでそれを行うことができます。まず、select() システム コールを使用して、データが使用可能かどうかを調べます。ここに例があります: http://www.developerweb.net/forum/showthread.php?t=2933

2 つ目は、データが利用可能であることを select が示している場合は、大きなブロック サイズで read() を 1 回だけ呼び出します。利用可能なバイト数、またはブロックのサイズのいずれか小さい方までのみを読み取ります。select() が true を返す場合、read() は常にすぐに戻ります。

于 2008-09-16T16:41:05.310 に答える
0

私はそれが可能だとは思いません。パイプは、パケット指向のプロトコルではなく、ストリーム指向のプロトコルを提供します。IOW、パイプに2回書き込む場合(1回はたとえば250バイト、もう1回はたとえば520バイト)、1回の読み取り要求でもう一方の端から取得するバイト数を知る方法はありません。256、256、そして残りを取得できます。

パイプにパケットを課す必要がある場合は、事前に決定された(または区切られた)バイト数をパケット長として書き込み、次に残りのパケットを書き込むことによって、自分で行う必要があります。select()を使用して読み取るデータがあるかどうかを確認し、read()を使用して適切なサイズのバッファーを取得します。バッファがある場合、パケット境界を決定するのはあなたの責任です。

于 2008-09-16T13:02:04.603 に答える
0

到着すると予想されるデータの量を知りたい場合は、パイプによって送信されるすべてのメッセージの先頭に、メッセージのサイズをいつでも書き込むことができます。したがって、たとえば、すべてのメッセージの先頭にデータの長さで4バイトを書き込み、最初の4バイトのみを読み取ります。

于 2008-09-16T13:02:17.347 に答える
0

パイプから来るデータの量を伝える移植可能な方法はありません。あなたができる唯一のことは、データを読み込んで処理することです。

そのためには、循環バッファのようなものを使用できます

于 2008-09-16T17:22:02.357 に答える
0

私はそれが可能だとは思わない.2つの端の間で(一方向で)プロセス間通信を提供するパイプのポイントではない. その主張が正しければ、送信はパイプへのデータのプッシュをまだ完了していない可能性があるため、長さを判断することは不可能です。

どのプラットフォームを使用していますか?

于 2008-09-16T12:53:05.390 に答える
-1

Windows では、いつでも を使用できますがPeekNamedPipe、とにかくそれをやりたいとは思いません。

于 2008-09-16T21:35:29.487 に答える