2015-01-02 2 views
1

동일한 아빠에 속한 두 개의 하위 프로세스가 생성되는 프로그램이 있습니다. 이제 프로그램은 컨트롤 C를 치는 것으로 시작한 다음 매번 컨트롤 Z를 눌러 작동합니다.파이프에서 값을 읽는 중 작동하지 않습니다.

목표는 자식 1에 대해 2 개의 숫자를 자식 2에 쓰고 자식 2는 숫자를 나누고 결과를 자식 1에 다시 쓰는 것입니다. 결과적으로 두 개의 파이프가 필요합니다 (fd 및 sd).

첫 번째 파이프가 정상적으로 작동하므로 번호가 다음과 같이 전송됩니다. 하위 2 (디버깅 용)에 정확한 숫자가 표시되므로 8과 2가있는 경우 ... 4의 올바른 답은 다음과 같습니다. 아이 2에 표시 지금은 무슨 잘못 당신이 그것을 실행할 수 있다면 누구나 볼 수 있다면이 "4"또는 어떤 결과가 다시 아이 1.

#include <stdio.h> 
#include <signal.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <time.h> 
#include <string.h> 
#include <stdlib.h> 


void handleSignal(int sig) 
{ 
    if (sig == SIGTSTP) 
    { 
     return; 
    } 
} 

int main() 
{ 
    int fd[2]; 
    int sd[2]; 
    int pipe1 = 0; 
    int pipe2 = 0; 
    pid_t fork1 = 0; 
    pid_t fork2 = 0; 
    int num1, num2, result; 
    int myJump = 0; 
    int returnResult = 99; 

    signal(SIGINT, handleSignal); 
    printf("Waiting for interrupt\n"); 
    pause(); 
    signal(SIGINT, SIG_IGN); 
    pipe1 = pipe(fd); 
    pipe2 = pipe(sd); 
    //pipe checks been omitted...for simplicity 

    fork1 = fork(); 
    //fork check been omited..for simplicity 

    signal(SIGTSTP, handleSignal); //wait till control Z is pressed 

    if (fork1 == 0) 
    { 

     dup2(fd[1], 1); 
    dup2(sd[0], 0); 
     close(fd[0]); 
    close(sd[1]); 

    while(1) 
     { 
      pause(); 
      int randNum1 = rand() % 9 + 1; 
      fprintf(stderr, "Child 1: %d\n", randNum1); 
      printf("%d\n", randNum1); 
      fflush(stdout); 
     scanf("%d", &returnResult); 
     fprintf(stderr, "result in A :%d \n", returnResult); 
     } 

    } 
    else if (fork1 > 0) 
    { 
     fork2 = fork(); 

     if (fork2 == 0) 
     { 
     signal(SIGTSTP, handleSignal); 
     dup2(fd[0], 0); 
     dup2(sd[1], 1); 
     close(fd[1]); 
     close(sd[0]); 

     if (myJump == 0) 
     { 
      pause(); 
      scanf("%d", &num1); 
      printf("CHild 2: %d\n", num1); 
      myJump = 1; 
     } 
     if (myJump == 1) 
     { 
      while (1) 
     { 
      pause(); 
      scanf("%d", &num2); 
      result = num2/num1; 
      fprintf(stderr, "result from B: %d \n", result); 
      num1 = num2; 
      printf("%d \n", result); 
     } 
     } 

    } 
     else 
    { 
     wait(); 
    } 
    } 
    else 
     { 
    printf("errror \n"); 
     } 

    return 0; 
} 

하는 것입니다 얻이 수없는 것 ... 먼저 컨트롤 C를 두드려서 컨트롤 Z를 계속해서 움직여야합니다. 그러면 아래와 같이 자식 A의 결과가 B의 결과와 일치하지 않음을 알 수 있습니다.

Waiting for interrupt 
^C^ZChild 1: 2 
result in A :99 
^ZChild 1: 8 
result in A :99 
result from B: 4 
^ZChild 1: 1 
result in A :99 
result from B: 0 

답변

2

파이프가 실제로 잘 작동하고 있습니다 ... 실패한 것은 scanf()입니다.

if (myJump == 0) 
    { 
     pause(); 
     scanf("%d", &num1); 
     printf("CHild 2: %d\n", num1); /* <== problem here */ 
     myJump = 1; 
    } 

을 ... 그리고 printf()가 잎 : 두 번째 자식 프로세스가 시작되면 호출 "아이 2 :"를 sd[] 파이프의 다음 데이터로. 따라서 첫 번째 자식 프로세스가 scanf()을 호출하여 두 번째 자식 결과를 읽으면 scanf()이 실패하고 returnResult은 변경되지 않습니다. scanf()이 실패했기 때문에 데이터가 스트림에 남아 있으며 이후 결과는 scanf()으로 동일하게 실패합니다.

수정 방법은 원하는대로 다릅니다. 당신이 당신의 두 번째 자식 프로세스가 그냥 첫 번째 패스의 결과로 읽을 수를 반환 할 경우, 단지 텍스트없이 단지 수를 작성하는 잘못된 printf()을 수정

if (myJump == 0) 
    { 
     pause(); 
     scanf("%d", &num1); 
     printf("%d\n", num1); /* <== Changed: number only, no text */ 
     myJump = 1; 
    } 

내가 추가해야합니다 위에서 언급 한 변경으로 문제가 해결되지만 일반적으로 scanf()에서 반환 여부를 확인하여 성공 여부를 확인하고 그렇지 않은 경우 적절한 조치를 취해야합니다.

+0

저는 'Child 2' 인쇄가 실제로 표준 오류로 진행되어 다른 프로세스로 전송되는 대신 프로세스를 모니터링하는 사람들이 볼 수 있다고 생각합니다. 정보를 디버깅하는 것은 일반적으로'stderr'로갑니다. 왜냐하면 파이프가 사라지지 않고 막히지 않기 때문입니다. ([신호를 사용하기 위해 부모와 자식 프로세스를 얻는 법을 참고하십시오.] (http://stackoverflow.com/questions/27697999/c-getting-a-parent-and-child-process-to-work-using-signals/)).) –

+0

@JonathanLeffler 다른 어린이는 그 시점에 숫자를 받기를 기대하고 있습니다. fprintf가 stderr로 변경 되었다면 다른 프로세스에도 번호를 보내려면 다른 printf를 추가해야합니다. – Dmitri

관련 문제