使用php5-cgi
,fork()
和管道写了一个小脚本来与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;
}
我认为这是由于管道溢出造成的。我有办法解决这个问题吗?或者有没有其他方法来处理大量产品?
答案 0 :(得分:5)
管道缓冲区相对较小,通常为几千字节。孩子可以写到它,直到缓冲区满了;然后进一步写入将阻塞,直到读取了一些数据。
您的父母在尝试从管道中读取之前调用waitpid
。所以它正在等待孩子终止。但如果孩子被阻止尝试写,它将永远不会终止。所以在这种情况下你永远不会超过waitpid
。
您可能想要做的是在waitpid
循环后移动read/write
。然后孩子可以在阅读时继续写更多数据。当read()
最终失败时,可能是因为孩子退出并关闭了管道的末端。所以你当时可以waitpid
来获得退出状态并收获僵尸。
另外,检查所有系统调用的返回值!并在打开警告的情况下进行编译(这会提醒您忘记了#include <sys/wait.h>
)。