2015-01-02 14 views
1

我有一個程序,其中創建了屬於同一個父親的兩個子進程。現在程序開始按控制C,然後每次按控制Z按鈕。從管道中讀取值不起作用

目標是讓孩子1向孩子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