2017-04-03 5 views
-1

ここでは、パイプを閉じずにパイプに書き込んだ後、そのパイプをどのようにフラッシュできるかについて質問しています。 どのスレッドでも私はさまざまな提案を見ることができましたが、明確な解決策を見つけることができませんでした。ここでCを閉じないでフラッシングパイプ

は簡単な要約です:

  1. パイプ上のブロッキング読む回避するための最も簡単な方法は、読んでいる正確なバイト数を書くことであろう。

  2. パイプの代わりにptmxを使用することもできますが、人々はそれがあまりにも多いかもしれないと言いました。

注:これは、パイプ

にfsyncを使用することはできません任意の他のより効率的なソリューションがありますか?

編集:送信者がn文字を書きたいが、クライアントが(ただし、m> n)は、m個の文字を読み取ると

フラッシュが便利です。クライアントは別のm-n文字の待機をブロックします。送信者がクライアントと再び通信したい場合は、パイプを閉じるオプションなしに彼を去り、正確なバイト数を送信するだけでバグの良いソースになる可能性があります。

受信機は、このように動作し、それを変更することはできません。

while((n=read(0, buf, 100)>0){ 
    process(buf) 

ので、送信者が処理を取得したい:「FILE1」と「FILE2」はする必要がありますいる:

write(pipe[1], "file1\0*95", 100); 
write(pipe[1], "file2\0*95", 100); 

私が探しているのは、そのようなことをする方法です(区切り文字として\ nを使用する必要はありません)。

write(pipe[1], "file1\nfile2", 11); //it would have worked if it was ptmx 

(読み取りと書き込みを使用)

+2

これは[X-Y問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)と非常によく似ています。一般的に言えば、パイプを流す必要はないので、本当の問題は何ですか? –

+0

"pts"はどういう意味ですか? –

+0

@ジョン:私は擬似端末マスター/スレーブを指していました。元の投稿を更新しました。 –

答えて

1

fflush()という意味のフラッシングは、Cストリームとして表されていないため、パイプとは無関係です。したがって、フラッシュするユーザランドバッファは存在しません。同様に、fsync()もデータにバックエンドストレージがないため、パイプとは関係ありません。パイプに正常に書き込まれたデータは、正常に読み込まれるまではカーネル内とカーネル内にのみ存在するため、fsync()の作業はありません。全体的に、フラッシング/同期は、中間ストレージが関与する場合にのみ適用でき、パイプではそうではありません。

明確にすると、あなたの質問は、パイプを介した通信のためのメッセージ境界を確立することにあるようです。パイプの書き込み終了を閉じると、1つのメッセージだけではなく、通信の全体の流れの境界が示されることは間違いありませんが、もちろん最終的なものです。固有のメッセージ境界がないことも間違いありません。それにもかかわらず、あなたは、少なくとも多少ここで誤解のから作業しているようだ:

パイプ上のブロッキング読む回避するための最も簡単な方法は、 に読んでいる正確なバイト数を書くことであろう。

[...]

送信者がn 文字を書きたいが、クライアントがm文字(m> n)を読むときに、フラッシュが便利です。クライアント は、別のm-n文字の待機をブロックします。

読者がブロックするかどうかは、読者の実装方法に完全に依存します。特に、read(2)システムコールは、返される前に要求されたバイト数を確実に転送することを保証しません。それは、いくつかの状況下で短い読書をすることができます。詳細は明記されていませんが、少なくとも1文字はブロックせずに転送することができますが、要求された数は転送できません。同様のことがwrite(2)に適用されます。したがって、read()をブロックするのを防ぐ最も簡単な方法は、read()転送の呼び出しのために少なくともの1つをバイトでパイプに書き込むことです。

実際、人々は通常、反対の方向からこの問題に遭います:特定のバイト数を受け取ることを確実にする必要があるため、複雑な問題として短い読み込みの可能性に対処する必要があります。ループ内でread()を実行します)。それも考慮する必要がありますが、あなたが説明した状況でクライアントがブロックする可能性は低いという利点があります。それはあなたがそれと思うだけの問題ではありません。

しかし、どのような種類のストリーム通信でもメッセージ境界の問題があります。それに対処する必要があります。いくつかのアプローチがあります。最も一般的に使用される間

  • 固定長のメッセージがあります。受信側は必要なバイト数を正常に転送するまで読み取りを行います。関係するすべてのブロックは適切で必要なものです。このアプローチでは、想定したシナリオは単純に発生しませんが、作者はメッセージを埋め込む必要があります。

  • 区切られたメッセージ。受信者は、メッセージ区切り文字(改行文字またはヌルバイトなど)を受信したことを検出するまで読み取ります。この場合、受信者は、メッセージ境界がread()コールによって転送されたバイトシーケンスと整列しない可能性のために準備する必要があります。チャネルを閉じることによってメッセージの終わりをマークすることは、この代替案の特殊なケースと考えることができます。

  • 埋め込まれたメッセージ長のメタデータ。これはさまざまな形をとることができますが、最も簡単な方法の1つは、メッセージを固定長の整数メッセージ長フィールドとそのバイト数のメッセージデータで構成することです。読者は、あらゆる点で何バイト読み込む必要があるかを知っているので、不必要にブロックすることはありません。

これらは、プロセス間通信を行うためのアプリケーション層プロトコルを実装するために、個別にまたは組み合わせて使用​​することができます。当然のことながら、通信の当事者は、通信が成功するためのプロトコルの詳細について合意しなければならない。

+0

お返事ありがとうございます。私は元の質問にいくつかの注釈を追加しましたが、私が見ているのはこれに対する答えです。「状況によっては短い読書をすることができます。 –

+0

@AntonisParagas、私はすでに私の答えで可能な限り最大限に取り組んできました。「**詳細は不明ですが**、ブロッキングなしで少なくとも1文字は転送できますが、通常は短読に頼ることができます。全体の番号が要求されました。つまり、 'read()'は少なくとも1バイトを転送できるときには通常ブロックされません。 –

関連する問題