我对 C 中的子进程和管道有疑问。
我的程序创建了两个子进程(silblings)和两个管道。父亲从stdin
中读取并通过第一个管道发送数据。第一个 child 将 stdin
重定向到第一个管道,将 stdout
重定向到第二个管道。之后, child 运行 gzip -cf
和 execlp(3)
。第二个 child 从第二个管道读取数据并将数据写入 stdout
(或文件)。
我试过了,但它不适用于二进制数据。如果第一个 child 仅通过第二个管道发送文本数据(不使用 gzip)并且第二个 child 读取它,则程序运行良好。但是,如果我将 gzip 与 execlp()
一起使用,并且进程写入二进制数据,则该程序无法运行,因为我没有获得所有数据。
部分代码如下:
第一个 child :
/* 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"!");
第二个 child :
/* 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);
最佳答案
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
的返回值。
关于c - 通过管道 C 发送二进制数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20152375/