通过管道C发送二进制数据

时间:2013-11-22 18:55:11

标签: c binary fork pipe

我在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);

1 个答案:

答案 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的返回值。