質問

以下のこのコードは、ls -l | wc -l。 コードでは、親でclose(p [1])をコメントすると、プログラムはハングし、入力を待ちます。なぜそうですか?子はlsの出力をp1に書き込み、親はその出力をp0から取得する必要があります。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

main ()
{
  int i;
  int p[2];
  pid_t ret;
  pipe (p);
  ret = fork ();

  if (ret == 0)
    {
      close (1);
      dup (p[1]);
      close (p[0]);
      execlp ("ls", "ls", "-l", (char *) 0);
    }

  if (ret > 0)
    {
      close (0);
      dup (p[0]);
      //Doubt, Commenting the line below does not work WHy?
      close (p[1]);
      wait (NULL);
      execlp ("wc", "wc", "-l", (char *) 0);
    }
}
役に立ちましたか?

解決

pipe + fork は4つのファイル記述子を作成し、2つは入力です

フォークの前に、1つの入力と1つの出力を持つ単一のパイプがあります。

フォークの後に、2つの入力と2つの出力を持つ単一のパイプがあります。

パイプに2つの入力(procが書き込む)と2つの出力(procが読み取る)がある場合、他の入力を閉じる必要があります。そうしないと、リーダーにも閉じられないパイプ入力があります。

あなたの場合、親はリーダーであり、パイプの出力端に加えて、理論的にはスタッフができるパイプの開いたもう一方の端、または入力端を持っていますに書き込まれます。その結果、パイプがeofを送信することはありません。これは、子が終了しても、親の未使用fdによりパイプがまだ開いているためです。

したがって、親はデッドロックし、自分自身への書き込みを永久に待機します。

他のヒント

dup(p [1])」は、同じファイルを指す2つのファイル記述子があることを意味します。 p [1] は閉じません。明示的に行う必要があります。同様に、 ' dup(p [0])'を使用します。パイプから開いている書き込みファイル記述子がない場合、パイプから読み取るファイル記述子はゼロバイト(EOF)のみを返すことに注意してください。最後の書き込み記述子が閉じられるまで、読み取りプロセスは無期限にハングします。書き込み終了を dup()する場合、書き込み終了までに2つの開いているファイル記述子があり、読み取りプロセスがEOFを取得する前に両方を閉じる必要があります。

また、コードで wait()を呼び出す必要もありません。 ls リストがパイプが保持できるサイズよりも大きい場合、プロセスはデッドロックし、子は ls の完了を待機し、 ls は書き込まれたデータの読み取りを続行する子。

冗長な素材が取り除かれると、作業コードは次のようになります。

#include <unistd.h>

int main(void)
{
    int p[2];
    pid_t ret;
    pipe(p);
    ret = fork();

    if (ret == 0)
    {
        close(1);
        dup(p[1]);
        close(p[0]);
        close(p[1]);
        execlp("ls", "ls", "-l", (char *) 0);
    } 
    else if (ret > 0)
    {
        close(0);
        dup(p[0]);
        close(p[0]);
        close(p[1]);
        execlp("wc", "wc", "-l", (char *) 0);
    }
    return(-1);
}

Solaris 10では、警告なしでコンパイルされます。

Black JL: gcc -Wall -Werror -Wmissing-prototypes -Wstrict-prototypes -o x x.c
Black JL: ./x
      77
Black JL:

子が p [1] を閉じない場合、そのFDは親と子の2つのプロセスで開かれます。親は最終的に閉じますが、子は閉じません。したがって、FDは開いたままになります。したがって、そのFDの読者(この場合は子)は、それ以上の書き込みが行われる場合に備えて、いつまでも待機します。 p>

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top