문제

아래 코드는 ls -l |를 실행하기위한 것입니다 WC -L. 코드에서, 부모의 닫기 (p [1])를 댓글을 달면 프로그램이 매달려 입력을 기다립니다. 왜 그렇습니까? 아동은 P1에 LS의 생산량을 씁니다. 부모는 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 개는 입력입니다

포크 전에 하나의 입력과 하나의 출력이있는 단일 파이프가 있습니다.

포크 후에는 2 개의 입력과 2 개의 출력이있는 단일 파이프가 있습니다.

파이프에 대한 두 개의 입력 (Proc가 작성한)과 두 개의 출력 (Proc가 읽은 출력)이있는 경우 다른 입력을 닫아야합니다. 그렇지 않으면 독자에게는 파이프 입력이 닫히지 않는 파이프 입력도 있습니다.

귀하의 경우 부모는 독자이며 파이프의 출력 끝에도 개방되어 있습니다. 다른 끝, 이론적으로 물건을 기록 할 수있는 파이프의 입력 끝. 결과적으로, 파이프는 EOF를 보내지 않습니다. 아이가 나가면 부모의 미사용 FD로 인해 파이프가 여전히 열려 있기 때문입니다.

그래서 부모의 교착 상태는 영원히 스스로 글을 쓰기를 기다리고 있습니다.

다른 팁

'dup(p[1])'동일한 파일을 가리키는 두 파일 설명자가 있음을 의미합니다. 닫히지 않습니다 p[1]; 당신은 그것을 명시 적으로해야합니다. 마찬가지로 'dup(p[0])'. 파이프에서 읽는 파일 디스크립터는 파이프에 대한 열린 쓰기 파일 설명자가 없을 때 제로 바이트 (EOF) 만 반환합니다. 마지막 쓰기 설명자가 닫힐 때까지 읽기 과정이 무기한으로 매달려 있습니다. 만약 너라면 dup() 쓰기 끝에는 쓰기 끝에 두 개의 열린 파일 설명자가 있으며, 읽기 프로세스가 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는 부모와 자식의 두 가지 과정에서 열려 있습니다. 부모는 결국 닫히지 만 아이는 결코하지 않습니다. 그래서 FD는 열려 있습니다. 그러므로 해당 FD (이 경우 아이)의 모든 독자는 더 많은 글을 쓰는 경우를 대비하여 영원히 기다릴 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top