Fork-execパイプリダイレクトの問題

誰もこのコードの何が間違っているのか教えてもらえますか?

要約すると、入力パイプと出力パイプを作成し、fork-execは sort プログラムを作成します。親は辞書/usr/share/dict/words を読み取り、それを dup2() 'd sort 'のパイプに書き込みます同様に、その出力を読み込み、端末(親の標準出力)に出力します。あるいは、少なくとも、それは起こっているはずのことです。

バックトレースは、親が(コメント 'XXX'でマークされた)130行目の read()でハングアップすると言います。 sort はファイルの終わりを認識していませんが、 pipeIn の書き込み終了を閉じるとこれを「シグナル」する必要があります。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char** argv)
{
    int pipeIn[2];
    int pipeOut[2];

    if ((pipe(pipeIn)) == -1)
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    if ((pipe(pipeOut)) == -1)
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    pid_t child = fork();

    if (child == 0)
    {
       //This is child!

        if ((dup2(pipeIn[0], STDIN_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((dup2(pipeOut[1], STDOUT_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((dup2(pipeOut[1], STDERR_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeIn[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((execlp("sort", "-r", NULL)) == -1)
        {
            perror("execlp");
            exit(EXIT_FAILURE);
        }
    }
    else if (child == -1)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    else
    {
       //This is parent!

        if ((close(pipeIn[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        int dict = open("/usr/share/dict/words", O_RDONLY);

        if (dict == -1)
        {
            perror("open");
            exit(EXIT_FAILURE);
        }

        char buf[1024];
        int count;

        while ((count = read(dict, buf, sizeof(char) * 1024)) > 0)
        {
            putchar('.');

            if ((write(pipeIn[1], buf, count)) == -1)
            {
                perror("write 1");
                exit(EXIT_FAILURE);
            }
        }

        if (count == -1)
        {
            perror("read");
            exit(EXIT_FAILURE);
        }

        if ((close(dict)) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeIn[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        while ((count = read(pipeOut[0], buf, sizeof(char) * 1024)) > 0)//XXX
        {
            putchar('!');

            if ((write(STDOUT_FILENO, buf, count)) == -1)
            {
                perror("write 2");
                exit(EXIT_FAILURE);
            }
        }

        if (count == -1)
        {
            perror("read");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }
    }

    return EXIT_SUCCESS;
}

入力していただきありがとうございます(馬鹿げています)。

4
私は同意する - 相互参照の質問は多少異なる。
追加された 著者 Jonathan Leffler,
通常はパイプの sort の標準エラーを送信しません。呼び出し元のプロセスの標準エラー(端末である可能性が高い)と同じ場所に置かれます。
追加された 著者 Jonathan Leffler,
追加された 著者 wallyk,
私はすでにそれを読んでおり、それはむしろ異なっているようです。
追加された 著者 Doddy,

1 答え

Your problem is that you are not closing the unused ends of your pipe in the chile process. So you need to add the following code somewhere before the exec

    if ((close(pipeIn[1])) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }

    if ((close(pipeOut[0])) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
2
追加された
+1 - そうです。これは直感的ですが、子プロセスで標準入力または標準出力としてパイプを使用している場合、通常は pipe()によって返されたファイル記述子の両方
追加された 著者 Jonathan Leffler,
ええ、私は最初にそれを取得しませんでしたが、私は(私は今日まで持っていない)それについて考えていたので、種類の意味があります。フォークの後には、パイプに書き込むことができる2つのファイル記述子が効果的に存在します。したがって、書き込み終了のファイル記述子がすべて閉じられるまで、パイプからの読み取りで eof を得ることはできません。
追加された 著者 Sodved,
@code argv [0] は常にプロセス名です。 ps や他のプロセス情報にどのように表示されるかを制御できます。
追加された 著者 Sodved,
ありがとうございます、それは動作していますが、逆の順序で単語のリストを印刷していません。 execlp( "sort"、 "-r"、NULL); の構文が間違っていますか?
追加された 著者 Doddy,
ああ、 execlp( "sort"、 "sort"、 "-r"、NULL); にする必要があります。
追加された 著者 Doddy,