5

私はpipe()システムコールを使用して、(任意の数のコマンドを使用して)パイピングをサポートするシェルを作成しようとしています。

残念ながら、pipe()を使用することはあまりできませんでした。さまざまなオンラインリソースを数日間調べた後、実行と同じ効果を持つ過度に単純化されたプログラムをまとめて、ls | sort2つの兄弟の子プロセスでパイプを機能させることができるかどうかを確認することにしました。コードは次のとおりです。

#include <sys/wait.h>
#include <unistd.h>

void run(char *cmd) {
   char *args[2];
   args[0] = cmd;
   args[1] = NULL;

   execvp(cmd, args);
}

int main(void) {
    int filedes[2];
    pipe(filedes);

    pid_t pid_a, pid_b;

    if (!(pid_a = fork())) {
        dup2(filedes[1], 1);
        run("ls");
    }

    if (!(pid_b = fork())) {
        dup2(filedes[0], 0);
        run("sort");
    }

    waitpid(pid_a, NULL, 0);
    waitpid(pid_b, NULL, 0);

    return 0;
}

パイプは親で作成され、execvp()呼び出しの後、各子プロセスは、pipe()が親で作成するファイル記述子を継承することを知っています。プロセスでは、lsdup2()を使用して標準出力(1)をパイプの書き込み端にリダイレクトし、sortプロセスでは、標準入力(0)をパイプの読み取り端にリダイレクトしています。

最後に、両方のプロセスが終了するのを待ってから終了します。

私の直感では、これは機能するはずですが、機能しません。

助言がありますか?

4

4 に答える 4

6

使用していないパイプを閉じる必要があります。少なくともsort、標準入力が閉じられるまで標準入力から読み取ります。

この場合、まだ 2 つの開いているファイル記述子があるため、標準入力が閉じられることはありません。

  • ls 子の filedes[0] (これは ls が終了すると閉じられる可能性があります)
  • 親プログラムの filedes[0] (これは、ソートが終了するまで waitpid() として閉じられることはありませんが、親が標準入力を開いたままにするため、閉じられることはありません)

プログラムを次のように変更します

if (!(pid_a = fork())) {
    dup2(filedes[1], 1);
    closepipes(filedes);
    run("ls");
}

if (!(pid_b = fork())) {
    dup2(filedes[0], 0);
    closepipes(filedes);
    run("sort");
}
closepipe(filedes);
waitpid(pid_a, NULL, 0);
waitpid(pid_b, NULL, 0);

closepipes は次のようなものです

void closepipes(int *fds)
{ 
 close(fds[0]);
 close(fds[1]);
}
于 2011-10-07T21:03:17.023 に答える
4

親プロセスを呼び出す前waitpidに、必要のないパイプからすべてのファイル記述子を閉じる必要があります。これらは:

  • filedes[0]pid_a
  • filedes[1]pid_b
  • 両方filedes[0]filedes[1]親プロセスで

また、エラーが発生したことを意味する をpipe()返さfork()なかったことも確認する必要があります。-1

于 2011-10-07T21:10:17.943 に答える
3

親プロセスのパイプの書き込み側を (少なくとも) 閉じる必要があります。そうしないと、パイプの読み取り側が EOF ステータスを読み取らず、sort終了しません。

于 2011-10-07T20:59:46.447 に答える
1

このコードは正常に動作しています...

    #include <sys/wait.h>
    #include <unistd.h>
    using namespace std;

    void run(char *cmd) {
       char *args[2];
       args[0] = cmd;
       args[1] = NULL;

       execvp(cmd, args);
    }
    void closepipe(int *fds)
    { 
     close(fds[0]);
     close(fds[1]);
    }

    int main(int argc,char *argv[]) {

        int filedes[2];
        pipe(filedes);
        char lss[]="ls";
        char sorts[]="sort";
        pid_t pid_a, pid_b;
     chdir(argv[1]);
    if (!(pid_a = fork())) {
        dup2(filedes[1], 1);
        closepipe(filedes);
        run(lss);
    }

    if (!(pid_b = fork())) {
        dup2(filedes[0], 0);
        closepipe(filedes);
        run(sorts);
    }
    closepipe(filedes);
    waitpid(pid_a, NULL, 0);
    waitpid(pid_b, NULL, 0);

        return 0;
    }
于 2012-09-06T13:42:33.183 に答える