1

プロセスの同期に UNIX パイプを使用することで、飢えに陥ることはありますか? 例えば:

void pipesem_wait(struct pipesem *sem)
{
    char onebyte = 'A';
    if ( read( sem->rfd, &onebyte, sizeof( onebyte ) ) != sizeof( onebyte ) ) {
        perror( "read from pipe" );
        exit( 1 );
    }
}

これは、パイプから読み取る方法です。複数のプロセスがこのパイプから読み取りたい場合、すべての要求が特定の順序 (FIFO など) で処理されることは確実ですか?飢餓の?

4

1 に答える 1

1

多くの読み取りプロセスのどれがデータを読み取るかは保証できませんが、そのうちの 1 つだけが各バイトを読み取ることは保証できます。パイプは実際には、カーネル内の単なる共有バッファーであり、読み書きするための異なるファイルハンドルがあります。複数のプロセスがこれらのハンドルを共有している場合、スケジューラーがデータを取得するプロセスを決定します。

したがって、1 つまたは複数のプロセスでデータが読み取られないという飢餓を意味する場合、その可能性は十分にあります。データの書き込み速度が遅く、1 つのプロセスが書き込みと同じ速さでデータを消費できる場合、他のプロセスはデータを認識しない可能性があります。データ。一方、すべてのプロセスでラウンドロビンになる場合があります。これは、スケジューリングがどのように行われるかによって異なります。どちらの場合にも依存することはできず、動作は Unix フレーバー、さらにはそのフレーバーのバージョンとそれが実行されているハードウェアに依存する場合があります。

ただし、失われることなくすべてのデータが消費され、データが FIFO 順で読み出されることを信頼できます。"ABC"ただし、書き込みが行われ、プロセス1がそれを読み取り、次に書き込み"DEF"が行われ、プロセス2がそれを読み取ると想像してください。プロセス 1 がプロセス 2 の前に入力の処理を終了するように、これらのプロセスがスケジュールされるという保証はありません。そのため、パイプからデータを読み取る順序は FIFO ですが、その後はプロセスのスケジュール方法次第です。

以下の最初のコメンターが指摘しているwrite()ように、パイプへの呼び出しは、以下に相当するデータを書き込んでいる限りアトミックであることにも言及するPIPE_BUF価値があります (たとえば、私の Linux システムでは 512 バイトlimits.hです。同等のものをチェックインしてください)。これにより、データのブロックが、同じパイプに書き込む他のプロセスからのデータとインターリーブされないことが保証されます。この制限を超えると、標準はwrite()がアトミックかどうかを指定しません。また、データの大きなブロックの場合、部分的な書き込みが発生する可能性があることにも注意してください。これは常に処理する必要があります。詳細については、コメンターがリンクした SO の質問と回答を参照してください。

ただし、一度に 1 バイトずつデータを読み取っているように見えるので、一度に 1 バイトしか書き込んでおらず、これをある種のプロセス同期メカニズムとして使用していると思います。代わりに、同じ目標を達成するためのより洗練された方法である pthreads 条件変数で共有メモリを使用することを検討することをお勧めします

注: 移植性が重要な場合は、パイプに固執することをお勧めします。パイプは、さまざまなプラットフォームで動作する可能性が高いと思われます。pthreads のアプローチはかなり移植性があるはずですが、共有メモリはおそらく移植性がやや劣ります。

要するに、これを使用してプールからワーカー プロセスを起動し、どのプロセスが使用されているかを気にしない場合、パイプは IPC メカニズムとして正常に機能します。ただし、特定のプロセスを起動したい場合は、ワーカーごとにパイプを使用するか、その他のメカニズムを使用する必要があります。たとえば、 pthreads 条件変数を使用すると、 の代わりに を呼び出すことで、待機中のすべてのプロセスを起動できます。pthread_cond_broadcast()pthread_cond_signal()

それはあなたの質問に答えていますか?

于 2013-01-30T19:28:38.263 に答える