2

現在、2 つのプロセスをパイプライン処理するために 2 つのフォークを実行していますがwait(&status)、コマンドの後、シェルがハングしてプロンプトに戻らないため、間違っていると思います。待機を削除すると結果が表示されるため、パイプが機能していることがわかります。

任意のヒント?

pipe(mypipe);
pid1=fork();
if(pid1==0)
{       
    pid2=fork();
    if(pid2==0)
    {
        close(0);
        dup(mypipe[0]);
        close(mypipe[1]);
        execv(foundnode2->path_dir,arv2);
        exit(0);
    }
    close(1);
    dup(mypipe[1]);
    close(mypipe[0]);
    pid2 = wait(&status2);
    execv(foundnode1->path_dir,arv1);
    exit(0);
}
pid1 = wait(&status2);  
4

2 に答える 2

0

経験則: dup()orを使用dup2()してパイプの一方の端を標準入力または標準出力にマップする場合close()は、パイプ自体の両方の端をマップする必要があります。あなたはそうしていません。あなたの待機はプログラムが終了するのを待っていますが、パイプに書き込むことができるパイプが開いているプロセスがまだあるため、プログラムは終了しません。また、パイプを作成したプロセスは、それ自体はパイプを使用していないため (子プロセスがパイプを使用しているため)、パイプの両端を閉じる必要があります。C MiniShell — パイプラインの追加も参照してください。

また、最初の子が終了するのを待ってから 2 番目の子を起動するべきではありません (したがって、このpid2 = wait(&status2);行は悪い考えです)。パイプの容量はかなり小さいです。転送するデータの合計が大きすぎる場合、書き込み中の子は読み取り中の子が読み取るのを待ってブロックする可能性がありますが、書き込み中の子が終了するのを待っているため、読み取り中の子はまだ開始されていません (また、処理に長い時間がかかります)。このデッドロックは自動的に解決されます)。wait()パイプラインの 2 番目の部分が実行され、パイプラインの最初の部分からのデータが処理されるため、呼び出しなしで出力が表示されますが、シェルからさらにデータが来るのをまだ待っています。

これらのヒントを考慮に入れると、次のようになる可能性があります。

pipe(mypipe);
pid1 = fork();
if (pid1 == 0)
{        
    pid2 = fork();
    if (pid2 == 0)
    {
        close(0);
        dup(mypipe[0]);
        close(mypipe[1]);
        close(mypipe[0]);
        execv(foundnode2->path_dir, arv2);
        fprintf(stderr, "Failed to exec %s\n", foundnode2->path_dir);
        exit(1);
    }
    close(1);
    dup(mypipe[1]);
    close(mypipe[0]);
    close(mypipe[1]);
    execv(foundnode1->path_dir, arv1);
    fprintf(stderr, "Failed to exec %s\n", foundnode1->path_dir);
    exit(1);
}
close(mypipe[0]);
close(mypipe[1]);
pid1 = wait(&status1);

コマンドが失敗すると、エラーが標準エラーに報告されることに注意してくださいexecv()。また、0 の終了ステータスは成功のために予約する必要があります。EXIT_FAILURE1 は便利なエラー終了ステータスです。またはfromを使用できます<stdlib.h>

多くのエラー チェックがまだ省略されています。fork()操作が失敗する可能性があります。pipe()失敗する可能性があります。結果の 1 つは、2 番目fork()が失敗した場合でも、2 番目の子 ( で識別される) を起動することですfoundnode1->path_dir

また、パイプの作成を最初の子プロセスに移動することで、少し手間を省くことができることに注意してください (親はパイプを閉じる必要はありません (実際にはできません))。

int pid1 = fork();
if (pid1 == 0)
{
    int mypipe[2];      
    pipe(mypipe);
    int pid2 = fork();
    if (pid2 == 0)
    {
        close(0);
        dup(mypipe[0]);
        close(mypipe[1]);
        close(mypipe[0]);
        execv(foundnode2->path_dir, arv2);
        fprintf(stderr, "Failed to exec %s\n", foundnode2->path_dir);
        exit(1);
    }
    close(1);
    dup(mypipe[1]);
    close(mypipe[0]);
    close(mypipe[1]);
    execv(foundnode1->path_dir, arv1);
    fprintf(stderr, "Failed to exec %s\n", foundnode1->path_dir);
    exit(1);
}
pid1 = wait(&status1);
于 2012-11-30T23:07:43.317 に答える
0

2 つのプロセスを持つ単なるパイプであれば、私はまったく待ちません。親と子で fork して exec を実行するだけです。

int fd[2];
pipe(fd);
int pid = fork();
if (pid == -1) {
    /* error handling */
} else if (pid == 0) {
    dup2(fd[0], 0);
    close(fd[1]);
    execv(foundnode2->path_dir,arv2);
    /* error handling for failed exec */
    exit(1);
} else {
    dup2(fd[1], 1);
    close(fd[0]);
    execv(foundnode1->path_dir,arv1);
    /* error handling for failed exec */
    exit(1);
}
于 2012-11-30T23:05:49.617 に答える