我在C中遇到子进程和管道问题。
我的程序创建了两个子进程(silblings)和两个管道。父亲从stdin
读取并通过第一个管道发送数据。第一个子项将stdin
重定向到第一个管道,将stdout
重定向到第二个管道。之后,孩子与gzip -cf
一起运行execlp(3)
。第二个子节点从第二个管道读取并将数据写入stdout
(或文件中)。
我试了但是它不能用于二进制数据。如果第一个子节点仅通过第二个管道发送文本数据(不使用gzip)而第二个子节点读取它,则程序运行正常。但是如果我使用带有execlp()
的gzip并且进程写入二进制数据,则程序不起作用,因为我没有得到所有数据。
以下是代码的一部分:
第一个孩子:
/* Close the pipe-ends which are not needed [...] */
/* Redirect the stdin and stdout with dup2 [...] */
if(execlp(EXEC,EXEC_ARG0,EXEC_ARG1,(char*) 0) == -1) /* run execlp with 'gzip -cf' */
bail_out(EXIT_FAILURE,"Child_1: Cannot execute "EXEC_ARG0" "EXEC_ARG1"!");
第二个孩子:
/* Close the pipe-ends which are not needed [...] */
FILE *fd = NULL;
char str[4096];
fd = fdopen(pipefd_com2[0],"rb");
(void) fread(str,sizeof(str),1,fd); /* read from pipe */
(void) fclose(fd);
FILE *fw = NULL;
if(file_arg == NULL) /* check if there was a file as argument */
fw = stdout;
else
fw = fopen(file_arg,"wb");
if(fw == NULL)
bail_out(EXIT_FAILURE,"Failed to write file!"); /* does not return */
(void) fwrite(str,strlen(str),1,fw); /* write to stdout or file */
(void) fclose(fw);
答案 0 :(得分:2)
strlen
函数用于C风格的字符串,而不是二进制数据。此外,您对fread
的参数是错误的。第二个参数是您正在阅读的每个对象的大小。对于任意二进制数据,应该是1
,因为每个对象都是一个字节。这将使fread
的返回值成为您读取的字节数,这是您需要传递给fwrite
作为第三个参数的内容。
总之:
size_t bytes_read;
// ...
bytes_read = fread(str,1,sizeof(str),fd); /* read from pipe */
// ...
(void) fwrite(str,1,bytes_read,fw); /* write to stdout or file */
您还应该检查fread
的返回值。