C未命名的管道和叉子用于计算

时间:2016-12-08 17:41:09

标签: c linux pipe fork

所以我正在尝试创建接受用户输入的程序(例如50的价格)然后第一个孩子将其传递给第二个,第二个添加10个(价格现在是60),第三个然后是50(价格现在是110) )和4只打印/返回最终价格。我有fork in循环而且我正在创建管道,但价格总是相同的,每个孩子只添加10个。有什么问题或如何解决,以便它能按我的意愿运作。

我的代码:

int main(int argc,char *argv[])
{
int anon_pipe[2];
int n,N=4;
char value_price[100];

if(argc>1)
{
    int price=atoi(argv[1]);
    printf("%d\n",price);
    if(pipe(anon_pipe)==-1){
        perror("Error opening pipe");
        return -1;
    }
    for(n = 0; n < N; n++){
        switch(fork()){
            case -1:
                perror("Problem calling fork");
                return -1;
            case 0:
                close(anon_pipe[1]);

                read(anon_pipe[0],value_price,100);

                price+=10;

                sprintf(value_price,"%d \n",price);
                printf("Price: %d\n",atoi(value_price));

                write(anon_pipe[1],value_price,sizeof(value_price));

                _exit(0);
        }
    }
    close(anon_pipe[0]);
    sleep(1);
    close(anon_pipe[1]);
}

return 0;
}

2 个答案:

答案 0 :(得分:1)

你似乎认为分叉会让孩子从程序的开头开始。情况并非如此,当fork()被调用

时,分叉会使孩子从同一行开始

例如,请看这里的代码:

            read(anon_pipe[0],value_price,100);

            price+=10;

            sprintf(value_price,"%d \n",price);
            printf("Price: %d\n",atoi(value_price));

看到你增加price的值,但你从未从管道中读取该值。所以所有孩子总是输出+10到他们各自的管道。

答案 1 :(得分:0)

您应该检查函数调用的返回值是否有错误代码。如果你已经完成了,你就会检测到这种呼叫组合产生的错误:

            close(anon_pipe[1]);

            // ...

            write(anon_pipe[1],value_price,sizeof(value_price));

很有可能,你也会发现很多这些电话......

            read(anon_pipe[0],value_price,100);

...在没有阅读任何内容的情况下发出文件结尾信号。至少,您需要read()的返回值来确定放置所需字符串终止符的位置(在将缓冲区用作字符串之前未能放置)。

作为一般规则, 强制性 可以处理read()write()的返回值,因为除了可能性之外error / EOF,这些函数可能执行短数据传输而不是完整传输。返回值告诉您传输了多少字节,确定是否循环以尝试传输更多字节。

此外,您的所有进程都使用相同的管道进行相互通信。你可能会很幸运,但很可能至少有时你最终会出现乱码。你真的应该为每对通信进程(包括父进程)创建一个单独的管道。

此外,请勿使用sleep()来同步进程。它不能可靠地工作。相反,父级应为其每个子进程wait()waitpid(),但只有在启动它们并执行所有必需的管道端处理之后。等待子进程也会阻止他们在退出后的任何重要时间内保留僵尸。当主进程退出而不是继续进行任何其他工作时,这并不重要,如在这种情况下,但是否则它构成资源泄漏(文件描述符)。你应该养成等待孩子过程的好习惯。

当然,如果你实际上没有写下你想写的数据,那么所有这些都没有实际意义; @SanchkeDellowar在他的回答中解释了你是如何做不到的。