2013-05-20 96 views
0

我想讓UNIX管道正確提示用戶輸入。我必須使用單個管道創建3個子進程。每個子進程都要求用戶輸入一個整數並將其寫入管道。父進程顯示全部三個整數以及每個寫入管道的進程的processid。如何正確地爲用戶輸入提供UNIX管道提示?

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

int main(int argc, char argv[]) { 
    int input = 0; 
    int pd[2]; 
    int i =0; 
    int buffer[100]; 
    int output = 0; 

    if (pipe(pd) == - 1) { 
     fprintf(stderr, "Pipe Failed"); 
    } 

    for (i=0; i<3; i++) { 
     if (fork() == 0) { // child process 
      printf("\nMy process id is: %d", getpid()); 
      printf("\nEnter an integer: "); 
      scanf("%d", &input); 
      if (write(pd[1], &input, sizeof(int)) == -1) { 
       fprintf(stderr, "Write Failed"); 
      } 
      return (0); // Return to parent. I am not really sure where this should go 
     } // end if statement 
    } // I am not quite sure where the for loop ends 

    // Parent process 
    close(pd[1]); // closing the write end 

    for (i = 0; i < 3; i++) { 
     if (read(pd[0], &output, sizeof(int))== -1) { 
      fprintf(stderr, "Read failed"); 
     } 
     else { 
      buffer[i] = output; 
      printf("Process ID is: %d\n", pid); 
     } 
    } 
    printf("The numbers are %d, %d, %d", buffer[0], buffer[1], buffer[2]); 
    return(0); 
} 

編輯後,我現在得到的輸出:

My process id is: 2897 
Enter an integer: My process id is: 2896 
Enter an integer: 
My process id is: 2898 
Enter an integer: 4 
Process ID is: 2898 
78 
Process ID is: 2898 
65 
Process ID is: 2898 
The numbers are 4, 78, 65 

這是拉近了許多,但我還不知道如何使該子進程的父等待。當試圖打印每個號碼及其進程ID時,只會打印最近的進程ID。

所有的printf語句在scanf語句之前執行,所以我不能輸入任何內容,直到它提示3次。

+0

你已經給出了三個獨立的,不協調的進程無權訪問終端。 *當然*他們交錯輸入和輸出:這就是你告訴他們要做的事情。 – dmckee

回答

0

在任何給定時間只有一個進程可以與用戶通話。你需要安排好孩子2在孩子1完成之前不做任何事情,等等。最簡單的方法是在分離下一個孩子之前,爲每個孩子連續填寫父母wait()編輯:這將是這個樣子:

for (i = 0; i < 3; i++) { 
    pid_t pid = fork(); 
    if (pid == -1) { 
     perror("fork"); 
     return 1; 
    } else if (pid == 0) { 
     // your existing child code goes here 
    } else { 
     // parent: 
     int status; 
     if (waitpid(pid, &status, 0) != pid) { 
      perror("wait"); 
      return 1; 
     } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { 
      fprintf(stderr, "child %d unexpected exit %d\n", i, status); 
      return 1; 
     } 
    } 
} 

由於寫入管道的數據量是非常短的(總共不到PIPE_BUF字節; PIPE_BUF是保證至少512),就可以安全地延遲閱讀管道,直到所有兒童退出。如果孩子們發回更長的信息,情況就不會如此。

main返回一個整數。第一個循環中的return;聲明應該是return 0;,最後需要有另一個return 0;(在最後的printf之後)。

您的第一個for循環結束於它應該結束的位置,即嵌套的if語句之後。你可以圍繞它放置另一套大括號 - 在for (...)之後的右大括號,右大括號,你有// I am not quite sure評論 - 很多人會認爲更好的風格,但你不必這樣做。

+0

在使用for循環時,我在哪裏使用父級wait()作爲子進程?我認爲我可以fork()一個子進程,然後等待()並再次分叉,但這會要求我放棄for循環並複製粘貼子進程三次(除非有更好的方式,我錯過了)。另外,爲什麼輸出顯示我奇怪的數字,而不是我輸入的數字?我認爲他們是數字的地址,但是如果我解引用它們,編譯器會說我正在從整數中指出沒有投射的指針。 – Matador89

+0

我編輯了一個示例fork-and-wait循環到我的答案中。 Guillaume解決了你奇怪的數字問題。 – zwol

0
if (read(pd[0]), &output, sizeof(int))== -1) 
      ^// this is wrong 

括號不正確,但我認爲這是一個錯字。

只有當讀取失敗,你也更新緩衝......它應該是:

if (read(pd[0], &output, sizeof(int))== -1) { 
    fprintf(stderr, "Read failed"); 
} 
else { 
    buffer[i] = output; 
} 

有許多方法這段代碼可以改善,雖然。看看其他答案並編譯你的程序(-gall with gcc)

+0

謝謝。我不相信我完全忽略了這一點。我改變了它,數字正確顯示。我修好了這個錯字,但忘了在這裏更新它。我現在編輯了這個問題。我查看了其他答案,幾乎所有這些答案都涉及使用dup函數的多個管道,但我還沒有處於該級別。你能否解釋我的代碼還有哪些可以改進的地方(如果你不介意的話)。謝謝。 – Matador89