4

私はとを使用するプログラムを持っていpopenますpclose

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
int main(void)
{
    FILE *fp = NULL;
    int ret_val = 0;

    fp = popen("ls *", "r");
    if (NULL == fp)
    {
        printf("popen error\n");
        return 1;
    }

    ret_val = pclose(fp);
    if (-1 == ret_val)
    {
        printf("pclose error\n");
        return 1;
    }
    else
    {
        printf("%d,%d,%d\n",ret_val, WIFEXITED(ret_val), WEXITSTATUS(ret_val));
    }
    return 0;
}

プログラムの出力は次のとおりです。

./test
Broken Pipe
36096,1,141

私の質問は次のとおりです。

  1. なぜ「壊れたパイプ」があるのですか?
  2. 終了ステータスコード141はなぜですか?「ls*」は正常に実行されたと思うので、終了ステータスは0である必要があります。
4

1 に答える 1

7
  • lsSIGPIPE シグナルが発生しているため、「壊れたパイプ」が表示されます。
  • ls閉じたパイプに出力しようとしているため、SIGPIPE が発生します。
  • あなたのプログラムはpclose()あなたのpopen().

のこの動作は、ドキュメントpcloseを読むことでさらに理解できます。基本的に、次のようになります。pclose

  1. 呼び出しによって開かれたストリームを閉じpopen()ます。
  2. コマンドが終了するまで待ちます。
  3. コマンドの終了ステータスを返します。

ストリームを閉じてからコマンドが終了するのを待つため、ストリームが閉じられたlsにストリームに書き込もうとすることがあるため、前述のシナリオが発生します。

さらに、kingsindian が指摘したように、SIGPIPE は常に発生するとは限りません。これは、メイン プロセスが を呼び出す前に、コマンドが実際に作業を終了できるためpclose()です。この動作は予測できないため、何らかの同期を実装することをお勧めします。プログラムが常にどのような状態にあるかを常に正確に知りたいと思うでしょう。

補足として、パイプはプロセス間通信を目的としていました。メイン プロセスがパイプを開いたり閉じたりするだけfork()の場合は、 and を使用したほうがよい場合がありますexec()

于 2013-03-22T07:26:21.693 に答える