写了一个小脚本来处理 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;
}
我认为这是由于管道溢出造成的。我有什么办法可以解决这个问题吗?或者是否有任何替代方法来处理大输出?
最佳答案
管道缓冲区比较小,一般只有几Kbytes。 child 可以写入它直到缓冲区已满;然后进一步的写入将阻塞,直到读取了一些数据。
你的 parent 调用 waitpid
在尝试从管道读取之前。所以它正在等待 child 终止。但是如果 child 试图写被阻止,它永远不会终止。所以你永远不会越过 waitpid
在这种情况下。
您可能想要做的是移动 waitpid
在read/write
之后环形。然后 child 可以在您阅读时继续写入更多数据。当 read()
finally 失败了,很可能是因为 child 已经退出并关闭了它的管道末端。所以你可以做 waitpid
在那个时候获取退出状态并收获僵尸。
此外,检查所有系统调用的返回值!并在打开警告的情况下进行编译(这会提醒您您忘记了 #include <sys/wait.h>
)。
关于C 管道无法进行大量写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36565255/