[英]SIGPIPE in bidirectional messaging with two pipes
嗨,我要开发这个程序,该程序可以创建4个孩子,然后依次使它们执行简单的操作。 第一个将进行求和,第二个将进行求和,第三个将进行乘法,第四个将进行除法。 父亲将用他希望孩子“计算”的两个数字在套接字上写入字符串,每个孩子都应阅读此字符串,提取数字并进行操作。 显然,由于是两个管道,由于在孩子中的读取,父亲每次都要写字符串。 我真的不明白为什么在第二次迭代中,我在父亲的著作中收到了SIGPIPE。 有人可以解释我为什么吗? 我在调试上损失了3天,但没有找到任何东西。 非常感谢你。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
/*
fd_0 padre escribe y hijo lee ==== padre cierra fd_0[0] y hijo cierra fd_0[1]
fd_1 hijo escribe y padre lee === padre cierra fd_1[1] y hijo cierra fd_1[0]
*/
int main (int argc, char * argv[]){
char * str = malloc(100*sizeof(char));//hijo
char readbuffer_h[150];
char * stringa = malloc(100*sizeof(char));//padre
char readbuffer_p[150];
int a,b;
int x,y;
int n = 4;
int i,status,nbytes, pipe_status;
int pid, ppid,yo,padre;
int fd_0[2], fd_1[2] ;
pipe_status=pipe(fd_0);
if(pipe_status==- 1) {
perror("Error creando la tuberia 0\n");
exit(EXIT_FAILURE);
}
pipe_status=pipe(fd_1);
if(pipe_status== -1) {
perror("Error creando la tuberia 1 \n");
exit(EXIT_FAILURE);
}
for(i=0; i< n; i++){
if ((pid=fork()) <0 ){
printf("Error al emplear fork\n");
exit(EXIT_FAILURE);
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
else if (pid ==0){// soy el hijo
yo = getpid();
padre = getppid();
printf("HIJO: %d, mi padre es: %d\n", yo, padre);
close(fd_0[1]);
close(fd_1[0]);
//TODO
nbytes = read(fd_0[0], readbuffer_h, sizeof(readbuffer_h));
sscanf(readbuffer_h, "%d,%d", &x, &y);
switch(i) {
case 0 :
//TODO
sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. La suma es %d", yo,x,y,(x+y));
break;
case 1 :
//TODO
sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. La resta es %d", yo,x,y,(x-y));
break;
case 2 :
//TODO
sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. El producto es %d", yo,x,y,(x*y));
break;
case 3 :
//TODO
sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. El cociente es %d", yo,x,y,(x/y));
break;
}
write(fd_1[1], str, strlen(str));
exit(EXIT_SUCCESS);
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
else{ //soy el padre
yo = getpid();
printf("PADRE:%d\n", yo);
a = 3; b = 4;
close(fd_0[0]);
close(fd_1[1]);
sprintf(stringa,"%d,%d",a,b);
printf("Stringa padre : %s\n", stringa);
fflush(stdout);
write(fd_0[1],stringa,strlen(stringa)); // questa write non va a buon fine
wait(&status);
read(fd_1[0], readbuffer_p, sizeof(readbuffer_p));
printf("%s\n",readbuffer_p);
fflush(stdout);
}
}
close(fd_0[0]);
close(fd_0[1]);
close(fd_1[0]);
close(fd_1[1]);
return 0;
}
通过尝试使用相同的管道与每个孩子进行通信,您正陷入困境。
您在程序的开头创建两个管道。 在循环的第一次迭代中,父级派生,而子级继承所有父级的打开文件描述符。 孩子关闭管道两端不需要,和父关闭管道两端不需要 。 交流按计划进行(我想),到目前为止一切顺利。
但是现在考虑循环的第二次迭代。 您再次进行分叉,并且子级再次继承父级的打开文件描述符。 但是现在,孩子想要使用的文件描述符在循环的上一次迭代中被父对象关闭了。 我对孩子在尝试使用这些文件描述符时得到的是EPIPE
而不是EBADF
感到有点惊讶,但是对于读取尝试失败,我一点也不感到惊讶。
最干净的方法是为每个孩子创建一对新的管道,而不是尝试重用一组管道。 如果要使其仅与一对配合使用,则父进程必须避免关闭任何管道末端(尽管子进程可以根据需要关闭其副本)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.