使用未命名的管道传递int数组

时间:2016-12-10 11:12:13

标签: c pipe

我必须创建一个创建4个孩子的程序。第一个子应该只传递一个int数组(数组从参数传递)到下一个,第二个应该将所有值增加20%并传递它们,第三个应该增加它们30%,第四个应该将它们全部打印出来。到目前为止,我设法做到了这一点,但我还没有完全理解管道,或者更确切地说是如何通过它们传递数组。

编辑:计算出大部分内容,但现在我的程序有时会挂起并且不会处理输入。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char* argv[])
{
int kom_pipe[2];
int kom_pipe2[2];
int n,i;
double prices[argc-1];

pipe(kom_pipe);
pipe(kom_pipe2);

for(n = 1; n<argc; n++){//fill array
    prices[n-1] = strtol(argv[n],NULL, 10);
}

//write(kom_pipe[1],&prices,sizeof(int)*(argc-1));

for(n = 0; n<4; n++){
    switch(fork()){
        case -1:
            perror("error with fork");
        return -1;
        case 0:;
            double prices2[argc-1];         
            if(n==0){
                close(kom_pipe[1]);
                close(kom_pipe2[0]);
                //read(kom_pipe[0],&prices2,sizeof(int)*(argc-1));      
                write(kom_pipe2[1],&prices,sizeof(double)*(argc-1));
                /*for(i = 0; i<argc-1; i++){
                    printf("%.5f ",prices[i]);
                }
            printf("\n");*/


            }else if(n==1){
                close(kom_pipe[0]);
                close(kom_pipe2[1]);
                read(kom_pipe2[0],&prices2,sizeof(double)*(argc-1));        


                for(i = 0; i<argc-1; i++){
                    prices2[i]*=1.2;
                }
                write(kom_pipe[1],&prices2,sizeof(double)*(argc-1));


            }else if(n==2){

                close(kom_pipe2[0]);
                close(kom_pipe[1]);
                read(kom_pipe[0],&prices2,sizeof(double)*(argc-1)); 
                for(i = 0; i<argc-1; i++){
                    prices2[i]*=1.3;
                }
                write(kom_pipe2[1],&prices2,sizeof(double)*(argc-1));


            }else if(n==3){
                close(kom_pipe[0]);
                close(kom_pipe2[1]);
                read(kom_pipe2[0],&prices2,sizeof(double)*(argc-1));
                for(i = 0; i<argc-1; i++){
                    printf("%.5f ",prices2[i]);
                }
            printf("\n");
        }
    close(kom_pipe[0]);
    close(kom_pipe2[0]);
    close(kom_pipe[1]);
    close(kom_pipe2[1]);
    _exit(0);
    }
}

close(kom_pipe[0]);
close(kom_pipe2[0]);
sleep(1);
close(kom_pipe[1]);
close(kom_pipe2[1]);
for(n = 0; n<4; n++){
    wait();
}   
return 0;
}

1 个答案:

答案 0 :(得分:1)

您的计划受race conditions约束。您创建的子项可以按任何顺序执行,实际上也可以并行执行。因此,如果n == 0首先发生,然后是n == 3,则输入由前者写入kom_pipe2,后者从kom_pipe2读取,打印不变,其他两个子进程将挂起,因为n == 1正在等待其他人已声明的输入,而n == 2依赖于n == 1。你对这个阵列的写作和阅读大多没有问题,只是不要将同一个管道用于两个不同的目的。

write中的一个在中间被中断而read找不到整个数据时,这仍然可能在罕见的情况下中断。这是read的返回值是什么。理想情况下,您应该编写一个循环,尝试以递增方式填充缓冲区,并且只有在完全接收到数据后才会退出。在具有几个字节有效载荷的管道中,这不会成为问题,但它是带有IP套接字的日常面包。

请注意,与序列中的所有操作相比,您的代码没有任何优势。即使你作为一个整体传递初始数组,如果他们逐个读取double,那么路上的过滤器可以更好地并行化。如果这是一个可能是预期的任务。

作为附言,

  • 如果您将_exit()替换为exit(),则不需要关闭所有管道,而是为您完成的。在任何情况下,您都不需要在父进程中关闭它们。是否有特定原因不使用exit()

  • 最后sleep()完全不必要,任意1秒不是好代码的标志。 wait()将负责等待子进程。 (还要检查其返回值,以观察除SIGCHLD之外的其他信号的中断。)