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

标签 c binary fork pipe

我对 C 中的子进程和管道有疑问。

我的程序创建了两个子进程(silblings)和两个管道。父亲从stdin 中读取并通过第一个管道发送数据。第一个 child 将 stdin 重定向到第一个管道,将 stdout 重定向到第二个管道。之后, child 运行 gzip -cfexeclp(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/

相关文章:

c - 子进程执行某些系统命令的结果无法通过管道发送到父进程

c++ - 要遵循的技巧

子进程不读取管道

c - popen2 : reading works, 写入不

string - 为什么我们需要 node.js 中的缓冲区?

binary - 有符号和无符号二进制有什么区别

go - 从Golang中的4,3和1位数据创建8位二进制数据

使用 Fork() 计算多个文件的行数,其中每个 child 单独运行

iphone - CFArray 和 NSArray 的区别

c - 在 C 中,当在 if 语句的条件中使用它们时,哪些值等于 true 或 false?