我必须创建一个创建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;
}
答案 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
之外的其他信号的中断。)