2017-10-15 1 views
0

나는 파이프라는 노드를 통해 통신하는 프로세스로 구성된 링크 된 목록을 만들어야하는 작업을하고 있습니다. 프로그램은 루트 프로세스와 노드 1이라는 하위 프로세스로 시작해야합니다. 사용자에게 네 가지 옵션이 제공됩니다. 사용자가 노드 (프로세스)를 추가 할 수있는 옵션 1에 고정되어 있습니다.자식 프로세스에서 파이프 읽기 두 번째 읽기에 걸려

루트 프로세스는 사용자 입력을 요청하는 유일한 프로세스 여야합니다. 나머지 블록은 읽기 블록에 도달 할 때까지 반복되어 기록되어야합니다.

사용자가 1을 입력하면 프로그램은 현재 프로세스가 마지막 노드 (이 경우 노드 1)인지 확인합니다. 그렇지 않은 경우, 프로세스는 각 분기 전에 작성된 파이프를 통해 입력을 다음 노드에 기록합니다. 그럴 경우 프로세스는 isLast 변수를 재설정하고 새 파이프와 분기를 작성합니다. 그러면 하위 프로세스 (노드 2)가 루프를 따라 돌아가고 읽음이 멈추며 부모는 발걸음을 따라 진행합니다. 루트는 다시 한번 사용 입력을 요구합니다.

문제는 프로그램이 더 문제가 한 번 겪고과 노드 2를 만드는이없는 것으로 보인다,하지만 통해 두 번째 시간, 노드 1은 루트가

어떤 도움 "노드 추가"에 쓰는 경우에도 중단 많이 고맙습니다! 마지막 노드가 파이프로부터 1을 판독 할 때

#include <stdio.h> 
#include <unistd.h> 

int main(){ 
    int isLast = 0; 
    int originPID = getpid(); 
    int input = 0; 
    int node; 
    int p[2]; 

    //Node 1 
    printf("%s\n", "Forking"); 
    pipe(p); 
    int pid = fork(); 

    //Set Node 1 to last 
    if(pid == 0){ 
     isLast = 1; 
     node = 1; 
    } 

    while(input != 4){ 
     //Node Read Block 
     if(getpid() != originPID){ 
      printf("stuck\n"); 
      read(p[0], &input, sizeof(input)); 
      printf("free\n"); 
     } 

     //MENU (Root Only) 
     if(getpid() == originPID){  
      sleep(1); 
      printf("%s", "User Options: Enter a number \n1. Add Node\n2. List Processes\n3. Remove Node\n4. Quit\n"); 
      scanf("%d", &input); 
     } 

     //(1) Add Node 
     if(input == 1){ 
      //Checks if last. 
      if(isLast == 1){ 
       isLast = 0;  //Reset isLast 

       //Create pipe and new process 
       printf("%s\n", "Forking"); 
       pipe(p); 
       pid = fork(); 
       if(pid == 0){  
        isLast = 1; 
        node++;  //Label Node 
       } 
      } 
      //Write to next node 
      else{  
       write(p[1], &input, sizeof(input));  
      } 
     } 
    } 
} 
+1

예를 들어 'a '을 입력하면 영원한 루프에 걸릴 수 있습니다. 'scanf ("% d", & input);'* never *는 일치합니다. 'scanf '의 반환 값을 확인하고 인수가 변환되지 않았다면 줄 끝까지 버려야한다. –

+0

또한, ** ** ** 라인이 무엇입니까, 귀하의 질문에있는 코드와 일치하지 않습니다. 61 질문에 코멘트입니다. 또한 [mcve]를 읽고 이것을 동일한 문제를 나타내는 최소한의 프로그램으로 만드십시오. –

+0

@AnttiHaapala 첫 번째 대답은 사용자가 'a'를 입력하면 프로그램이 영원한 루프에 들어갔다는 사실을 말하는 것입니까? 우리 교수가 지금 당장 올바른 의견을 제시하기를 원했기 때문에 나는 그 부분을 아직 다루지 않았습니다. 그러나 그뿐만 아니라 읽기 블록에 영향을 미칠까요? – DazedFury

답변

1

은 생성 되려고 새로운 노드와 통신하도록하여 새로운 파이프를 생성한다. 나는 그것이 pipe(p)이라고하는 이유라고 생각합니다. 그러나 이는 p[0]자신의 입력을 읽는 유일한 파일 핸들 사본이 포함되어 있기 때문에 문제가됩니다. 다음에 입력을 읽으려고 할 때, 다음 노드에 대해 설정 한 파이프에서 읽으려고 시도 할 것입니다. 실제로 이전 노드와의 연결이 끊어졌습니다.

pipe()이 파일 핸들을 쓰는 배열에 대한 마법은 없습니다. 핸들은 단지 정수입니다. 따라서 간단한 해결책은 자식이 배열 요소에 저장된 값을 참조하는 대신 부모로부터 상속받은 읽기 파일 설명 자의 사본을 만들어 사용하는 것입니다.

또한 포크 후 parent와 child는 각각 파이프의 끝 부분을 닫은 후 사용하지 않도록해야합니다. (부모는 읽기 끝을 닫고 자식은 쓰기 끝을 닫습니다.) 프로그램을 작동시키지 않고도 작업을 시작할 수는 있지만 최소한 파일 설명자가 누설됩니다. 경우에 따라 파일 설명자를 추가로 열어두면 프로그램이 중지 될 수 있습니다.

+0

답변을 작성해 주셔서 감사합니다. 죄송 합니다만 자녀가 파일 설명자의 복사본을 만들면 무슨 뜻인지 자세히 설명해 주실 수 있습니다. 이해가되지 않습니다.또한 우리 교수는 닫힌 파일 기술자가 재활용 될 것이므로이 과제에서 파이프를 닫지 말라고 우리에게 이야기했습니다. 우리는 분명히 원하지 않습니다. – DazedFury

+0

@DazedFury, 파일 설명자는 배열 요소 자체가 아닌 배열 요소에 저장된 값입니다. 동일한 값을 다른 위치 (즉, 다른 변수)에 저장하고 대신 다른 변수를 사용할 수 있습니다. 폐쇄에 관해서는, 만약 당신의 교수가 파일 기술자를 닫지 말라고 말하면, 물론 그들이 말하는 것처럼해야합니다. 파일 설명자 번호를 다시 사용할 수 있다는 것이 옳습니다. 나는 그것이 문제를 제시하는 이유가 무엇인지 생각할 수 없다. –

+0

그랬어! 대단한 일, 도와 줘서 고마워. – DazedFury

관련 문제