2016-04-12 15 views
2

php5-cgiと動作するように小さなスクリプトを書きました。fork()exec()とパイプを使用しています。以下のスクリプトは、php5-cgiの出力が小さい場合にうまく機能します。しかし、かなり大きくなると(入力ファイルに<?php phpinfo(); ?>を使用すると)何も返されません。Cパイプが大きな書き込みで機能しない

#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

小さいチャンクに書き込むデータを分割しますか? –

+2

まずは、常に:すべてのシステムコールの戻り値をチェックしてください。 –

答えて

5

パイプバッファーは比較的小さく、通常は数キロバイトです。子供は、バッファが満杯になるまでそれに書き込むことができます。データの一部が読み取られるまで、さらに書き込みがブロックされます。

あなたの親はwaitpidを呼び出してからパイプからの読み取りを試みます。だから、子供が終わるのを待っている。しかし、子供が書くことをブロックされている場合、それは決して終了しません。この場合、waitpidを決して通過することはありません。

read/writeループの後にwaitpidを移動してください。その後、子供はあなたがそれを読んでいくにつれて、より多くのデータを書き続けることができますread()が最終的に失敗すると、子が終了してパイプの終わりを閉じた可能性があります。したがって、その時点でwaitpidを実行して終了ステータスを取得し、ゾンビを刈り取ることができます。

また、すべてのシステムコールの戻り値を確認してください。警告をオンにしてコンパイルしてください(これは忘れたことをあなたに忘れてしまいました#include <sys/wait.h>)。

+0

'' 'waitpid'''が動いた!しかし、execから親スレッドへの出力全体を得るという保証はありません。私は正しいですか? – paarandika

+0

@paarandika:いいえ、正しくありません。あなたは全体の出力を得るでしょう。なぜあなたはそうしないと思いますか?親の 'read'はパイプバッファから読み込みますが、空になると' read'は子がもっと書き込むまでブロックします。しかし、バッファが空で、子がパイプを閉じたり終了した場合、 'read'はブロックを止めて0を返します。したがって、子によって書き込まれたすべてのデータが読み込まれるまで、ループは終了しません。 –

+0

パイプが一旦空になると、子がパイプを閉じていなくてもreadが返ると考えました。子プロセスの最後にはパイプが自動的に閉じられますか?私のコードでは私はそれを閉じる機会がないので。 – paarandika

関連する問題