2016-11-13 127 views
0

我想獲得一個父進程接受4個整數變量(a,b,c和x)的用戶輸入並將它們管到子進程。子進程評估ax^2 + bx + c並將結果r傳遞給顯示它的父級。親子通信通過管道在C

使用我現在的代碼,任何輸入的結果都爲1.打印語句的行爲使我認爲只有x正在讀取,但即使當我嘗試將x * x轉換爲r時, t得到正確的解決方案。我可能做錯了什麼?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/wait.h> 
#define PIPE_INPUT 0 
#define PIPE_OUTPUT 1 
#define INDENT 20 

void testError(int err, const char * str){ 
if (err < 0){ 
    perror(str); 
exit(EXIT_FAILURE); 
} 
} 

int main(){ 

int fd_toChild[2]; 
int fd_toParent[2]; 

int buff[20]; 

pid_t pid; 

testError(pipe(fd_toChild), "pipe"); 
testError(pipe(fd_toParent), "pipe"); 
testError(pid = fork(), "fork"); 

int a; 
int b; 
int c; 
int x; 
int r; 

if (pid > 0){  
    // this is the parent 


    int status; 

    while(1){ 

     close(fd_toChild[PIPE_INPUT]); 
     close(fd_toParent[PIPE_OUTPUT]); 


     printf("This program will evaluate a polynomial a(x^2) + bx + c. \n"); 
     printf("Please input an integer value for a: "); 
     scanf("%d", &a); 
     write(fd_toChild[PIPE_OUTPUT], &a, sizeof(a)); 

     printf("Parent writes value %d to a \n", a); 
     printf("Please input an integer value for b: "); 
     scanf("%d", &b); 
     write(fd_toChild[PIPE_OUTPUT], &b, sizeof(b)); 
     printf("Parent writes value %d to b \n", b); 

     printf("Please input an integer value for c: "); 
     scanf("%d", &c); 
     write(fd_toChild[PIPE_OUTPUT], &c, sizeof(c)); 
     printf("Parent writes value %d to c \n", c); 

     printf("Please input an integer value for x: "); 
     scanf("%d", &x); 
     write(fd_toChild[PIPE_OUTPUT], &x, sizeof(x)); 
     printf("Parent writes value %d to x \n", x); 

     close(fd_toChild[PIPE_OUTPUT]); 
     close(fd_toParent[PIPE_INPUT]); 

     read(fd_toParent[PIPE_INPUT], buff, sizeof(r)); 

     pid = wait(&status); 

     fprintf(stdout, "Parent received back the result %d.\n", r); 
     printf("The polynomial evaluates to %d \n", r); 

     close(fd_toParent[PIPE_OUTPUT]); 

     break; 
    } 
} 

else{ 
    // this is child 

    close(fd_toChild[PIPE_OUTPUT]); 
    close(fd_toParent[PIPE_INPUT]); 

    while(1){ 
     close(fd_toChild[PIPE_OUTPUT]); 
     close(fd_toParent[PIPE_INPUT]); 

     read(fd_toChild[PIPE_INPUT], buff, sizeof(a)); 
     printf("Child reads value %d from a \n", a); 

     read(fd_toChild[PIPE_INPUT], buff, sizeof(b)); 
     printf("Child reads value %d from b \n", b); 

     read(fd_toChild[PIPE_INPUT], buff, sizeof(c)); 
     printf("Child reads value %d from c \n", c); 

     read(fd_toChild[PIPE_INPUT], buff, sizeof(x)); 
     printf("Child reads value %d from x \n", x); r = a * x * x + b * x + c; 
     printf("x is %d", x); printf("r is %d", r); 

     write(fd_toParent[PIPE_OUTPUT], buff, sizeof(r)); 
     fprintf(stdout, "%*sChild is all done\n", INDENT, ""); 
     close(fd_toChild[PIPE_INPUT]); 

    } 
} 
return EXIT_SUCCESS; 
} 
+0

你正在做的多收。父進程:你首先關閉'fd_toParent [PIPE_INPUT]',然後立即嘗試讀取它。子進程:在循環結束時,關閉「fd_toChild [PIPE_INPUT]」,意味着循環的所有進一步迭代都不會按預期工作。如果您檢查讀/寫返回碼,所有這些類型的錯誤將很容易被發現。 – gudok

+0

哎呀。謝謝! –

+0

您的代碼同樣存在其他問題。 @gudok關閉'pipe'是正確的,但你也可以讀入'buff',但是嘗試從其他未初始化的變量中打印出來。 – tijko

回答

0

你有一些東西在拋棄你的程序。一個問題是,已經指出@gudok,在那裏你關閉fd_toParent[PIPE_INPUT],然後試圖從讀它後立即:

close(fd_toChild[PIPE_OUTPUT]); 
close(fd_toParent[PIPE_INPUT]); 
// just closed on the preceding line 
read(fd_toParent[PIPE_INPUT], buff, sizeof(r)); 

另外一個問題是,在你試圖read的子進程值的計算操作上:

read(fd_toChild[PIPE_INPUT], buff, sizeof(a)); 
printf("Child reads value %d from a \n", a); 

在這裏,您通過buff作爲read緩衝區,然後嘗試從a操作/打印。這會使a未初始化,這可以解釋爲什麼打印時您只是返回零。相反,你可以使用的地址,你的係數變量的運營商&

read(fd_toParent[PIPE_INPUT], &a, sizeof(a)); 

這同樣適用於bcx了。

而且還試圖打印出結果父時:

read(fd_toParent[PIPE_INPUT], buff, sizeof(r)); 

pid = wait(&status); 

fprintf(stdout, "Parent received back the result %d.\n", r); 
printf("The polynomial evaluates to %d \n", r); 

close(fd_toParent[PIPE_OUTPUT]); 

read(fd_toParent[PIPE_INPUT], buff, sizeof(r));你正在傳遞buff但打印出printf(The polynomial evaluates to %d \n", r)打印r這是父進程的內部未初始化的線。

您也一直在while(1)循環中包含大部分邏輯。由於父進程中的break不會影響程序的最終結果,但是如果您更改父進程循環,則重複調用close將會關閉管道的所有端點。

while(1){ 
    .... 
    close(fd_toChild[PIPE_OUTPUT]); 
    close(fd_toParent[PIPE_INPUT]); 
} 

沒有break您的管道將不會有任何用處。

我提出了一些修改,以顯示代碼的工作版本:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/wait.h> 

#define PIPE_INPUT 0 
#define PIPE_OUTPUT 1 
#define INDENT 20 


void testError(int err, const char * str) 
{ 
    if (err < 0) { 
     perror(str); 
     exit(EXIT_FAILURE); 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    int fd_toChild[2], fd_toParent[2], buff; 
    pid_t pid; 

    testError(pipe(fd_toChild), "pipe"); 
    testError(pipe(fd_toParent), "pipe"); 
    testError(pid = fork(), "fork"); 

    int a, b, c, x, r; 

    if (pid > 0){  
     // this is the parent 

     int status; 

     close(fd_toChild[PIPE_INPUT]); 
     close(fd_toParent[PIPE_OUTPUT]); 

     printf("This program will evaluate a polynomial a(x^2) + bx + c. \n"); 
     printf("Please input an integer value for a: "); 
     scanf("%d", &a); 
     write(fd_toChild[PIPE_OUTPUT], &a, sizeof(a)); 

     printf("Parent writes value %d to a \n", a); 
     sleep(1); 
     printf("Please input an integer value for b: "); 
     scanf("%d", &b); 
     write(fd_toChild[PIPE_OUTPUT], &b, sizeof(b)); 
     printf("Parent writes value %d to b \n", b); 
     sleep(1); 
     printf("Please input an integer value for c: "); 
     scanf("%d", &c); 
     write(fd_toChild[PIPE_OUTPUT], &c, sizeof(c)); 
     printf("Parent writes value %d to c \n", c); 
     sleep(1); 
     printf("Please input an integer value for x: "); 
     scanf("%d", &x); 
     write(fd_toChild[PIPE_OUTPUT], &x, sizeof(x)); 
     printf("Parent writes value %d to x \n", x); 
     sleep(1); 
     // XXX you close then attempt to read from it 
     //close(fd_toParent[PIPE_INPUT]); 

     read(fd_toParent[PIPE_INPUT], &buff, sizeof(buff)); 

     pid = wait(&status); 
     // XXX Here you are showing the results as your uninitialized variable "r" 
     fprintf(stdout, "Parent received back the result %d.\n", buff); 
     printf("The polynomial evaluates to %d \n", buff); 

     close(fd_toChild[PIPE_OUTPUT]); 
     close(fd_toParent[PIPE_OUTPUT]); 
    } else { 
     // this is child 

     close(fd_toChild[PIPE_OUTPUT]); 
     close(fd_toParent[PIPE_INPUT]); 

     read(fd_toChild[PIPE_INPUT], &a, sizeof(a)); 
     printf("Child reads value %d from a \n", a); 

     read(fd_toChild[PIPE_INPUT], &b, sizeof(b)); 
     printf("Child reads value %d from b \n", b); 

     read(fd_toChild[PIPE_INPUT], &c, sizeof(c)); 
     printf("Child reads value %d from c \n", c); 

     read(fd_toChild[PIPE_INPUT], &x, sizeof(x)); 
     printf("Child reads value %d from x \n", x); 
     r = a * x * x + b * x + c; 
     printf("x is %d\n", x); 
     printf("r is %d\n", r); 

     write(fd_toParent[PIPE_OUTPUT], &r, sizeof(r)); 
     fprintf(stdout, "%*sChild is all done\n", 0, ""); 

     close(fd_toChild[PIPE_INPUT]); 
     close(fd_toParent[PIPE_OUTPUT]); 
    } 

    return EXIT_SUCCESS; 
}