C管道无法正常写入

时间:2016-04-12 06:33:34

标签: c pipe

使用php5-cgifork()和管道写了一个小脚本来与exec()一起使用。当php5-cgi的输出很小时,下面的脚本运行良好。但是当它相当大时(在输入文件中使用<?php phpinfo(); ?>时),它不会返回任何内容。

#include<netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>

int main(int argc, char const *argv[]) {

  int status;
  int link[2];
  char out[4096];
  char * arg[3]={"php5-cgi","a.php",0};
  if (pipe(link)==-1){
    perror("pipe");
  }
  int pid=fork();
  if (!pid){
    dup2 (link[1], 1);
    close(link[0]);
    execvp("php5-cgi", arg);
  } else {
    waitpid(pid, &status,0);
    close(link[1]); // parent doesn't write
        char reading_buf[1];
        while(read(link[0], reading_buf, 1) > 0){
            write(1, reading_buf, 1);
        }
        close(link[0]);
  }
  printf("%s\n", "end");
  return 0;
}

我认为这是由于管道溢出造成的。我有办法解决这个问题吗?或者有没有其他方法来处理大量产品?

1 个答案:

答案 0 :(得分:5)

管道缓冲区相对较小,通常为几千字节。孩子可以写到它,直到缓冲区满了;然后进一步写入将阻塞,直到读取了一些数据。

您的父母在尝试从管道中读取之前调用waitpid。所以它正在等待孩子终止。但如果孩子被阻止尝试写,它将永远不会终止。所以在这种情况下你永远不会超过waitpid

您可能想要做的是在waitpid循环后移动read/write。然后孩子可以在阅读时继续写更多数据。当read()最终失败时,可能是因为孩子退出并关闭了管道的末端。所以你当时可以waitpid来获得退出状态并收获僵尸。

另外,检查所有系统调用的返回值!并在打开警告的情况下进行编译(这会提醒您忘记了#include <sys/wait.h>)。