通过C中的管道进行亲子沟通

时间:2016-11-13 17:01:17

标签: c

我正在尝试让父进程接受4个整数变量(a,b,c和x)的用户输入,并将它们传递给子进程。子进程计算ax ^ 2 + bx + c并将结果r传递给父进程,后者显示它。

使用我现在的代码,任何输入都会得到1的结果。打印语句的行为让我觉得只有x被读取,但即使我尝试将x * x转换为r,我也不会得到正确的解决方案。我能做错什么?

#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; 
}

1 个答案:

答案 0 :(得分: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; 
}