6

2 つの子プロセスを作成する必要があります。1 つの子は、コマンド「ls -al」を実行し、その出力を次の子プロセスの入力にリダイレクトする必要があります。これにより、入力データに対してコマンド「sort -r -n -k 5」が実行されます。最後に、親プロセスはそれ (データは既にソート済み) を読み取り、ターミナルに表示する必要があります。(プログラムを実行したときの) ターミナルでの最終結果は、次のコマンドをシェルに直接入力した場合と同じになるはずです: "ls -al | sort -r -n -k 5"。このために、次のメソッドを使用する必要があります: pipe()、fork()、execlp()。

プログラムはコンパイルされますが、端末に目的の出力が得られません。何が悪いのかわかりません。コードは次のとおりです。

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main()
{
    int fd[2];
    pid_t ls_pid, sort_pid;
    char buff[1000];

    /* create the pipe */
    if (pipe(fd) == -1) {
        fprintf(stderr, "Pipe failed");
        return 1;
    }

    /* create child 2 first */
    sort_pid = fork();
    if (sort_pid < 0) {                         // error creating Child 2 process
        fprintf(stderr, "\nChild 2 Fork failed");
        return 1;
    }
    else if(sort_pid > 0) {                     // parent process

        wait(NULL);                             // wait for children termination

        /* create child 1 */
        ls_pid = fork();
        if (ls_pid < 0) {                       // error creating Child 1 process
            fprintf(stderr, "\nChild 1 Fork failed");
            return 1;
        }
        else if (ls_pid == 0) {                 // child 1 process
            close(1);                           // close stdout
            dup2(fd[1], 1);                     // make stdout same as fd[1]
            close(fd[0]);                       // we don't need this end of pipe
            execlp("bin/ls", "ls", "-al", NULL);// executes ls command
        }

        wait(NULL);
        read(fd[0], buff, 1000);                // parent reads data 
        printf(buff);                           // parent prints data to terminal   
    }
    else if (sort_pid == 0) {                   // child 2 process
        close(0);                               // close stdin
        dup2(fd[0], 0);                         // make stdin same as fd[0]
        close(fd[1]);                           // we don't need this end of pipe
        execlp("bin/sort", "sort", "-r", "-n", "-k", "5", NULL); // executes sort operation
    }

    return 0;
}
4

1 に答える 1

3

waitls プロセスを作成する前に、並べ替えプロセスの親プロセスs を終了します。

並べ替えプロセスは、完了する前に入力を読み取る必要があります。そして、その入力は ls から来ており、wait. デッドロック。

両方のプロセスを作成してから、両方のプロセスを作成する必要がありwaitます。

また、ファイル記述子の操作が正しくありません。この呼び出しのペアでは:

close(0);
dup2(fd[0], 0);

dup2 は既存の fd 0 があればそれを自動的に閉じるため、クローズは冗長です。close(fd[0])dup2の後に実行する必要があるため、パイプのその端に関連付けられたファイル記述子は 1 つだけになります。本当に堅牢にしたい場合は、fd[0]==0すでにウィザーをテストする必要があります。その場合は、dup2 をスキップして閉じます。

そのすべてを他の dup2 にも適用します。

次に、パイプを開いたままにしている親プロセスの問題があります。パイプの両端を子に渡した後、親のパイプの両端を閉じる必要があると思いますが、最後readから奇妙なことがあります...なぜそこにあるのかわかりません。パイプラインが正しく実行された場合、パイプは後で空になるため、読み取るものは何もありません。いずれにせよ、必ず親を閉じる必要があります。そうしないと、すべてのライターが閉じられるまでパイプが EOF を示さないため、並べ替えプロセスが終了しません。fd[0]waitls|sortfd[1]

奇妙なreadことprintfに、読み取りバッファが終了しないため、おそらくクラッシュします'\0'

使用のポイントexeclpは、$PATHルックアップを行うため、指定する必要がないことです/bin/。ソートが にあるため、最初のテスト実行は失敗しました/usr/bin/。パスをハードコーディングする必要がないのに、なぜパスをハードコーディングするのでしょうか?

于 2013-06-01T20:39:04.767 に答える