2017-11-03 5 views
1

私はLinuxのCでシェルのコードを書いています。ここでは複数のパイプを実装しなければなりません(例えばA | B | c | D A、B、C、Dはコマンドです)。シェルは、同じpgidを持つコマンドごとに個別のプロセスを作成し、その入力と出力をpipe()システムコールを使用して接続します。すべての子が作成されると、親はこのpgidをtcsetpgrp()を使用してフォアグラウンドに来て、バックグラウンドに移動します。すべてが動作しますが、A、B、C、Dを実行している子供がいったん終了すると、Aを処理しているchild1だけが死亡し、sigchildハンドラと他の子供によって処理され、ctrl + cを押すまで何もしません。 ctrl + cが押されると、他のすべての子プロセスがシグナルハンドラによって刈り取られ、sigsuspendにある親プロセスが起動し、再びフォアグラウンドに戻ります。多くの子供のうち1人の子供だけが死んで残りはctrl + cを待つ

誰もがなぜ子供1だけが死んで、他の子供が終わっていない間にコントロールがどこにあるのか理解するのを助けてくれますか?

ここには、SIGINTハンドラのコードがあります。それは子供の必要な数を作成した後、ここ

空隙sigchld_handler(INT秒){

int olderrno = errno; 
sigset_t mask_all; 
sigset_t prev_all; 

sigfillset(&mask_all); 
while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { 
    sigprocmask(SIG_BLOCK, &mask_all, &prev_all); 
    NoOfChildrenToBeReaped--; 
    sigprocmask(SIG_SETMASK, &prev_all, NULL); 
} 
errno = olderrno; 

}

は、親のためのコードです。

//Get the pid of the first child and set it as the pgid of all the sibling children. 
if (i == 0) { 
    pgid = pid; 
} 
setpgid(pid, pgid); 

そして、ここでは親がバックグラウンドに行くプロセスが)、まだ刈り取らなければならないどのように多くの子供たちを追跡し、(sigsuspend後に戻ってフォアグラウンドに来ています。

if (BGProc) { 
    if (tcsetpgrp(STDIN_FILENO, pgid) == -1) { 
     printf(EXEC_ERROR, "Error in tcsetpgrp"); 
    } 

    while (NoOfChildrenToBeReaped) { 
     sigsuspend(&masknone); 
    } 

    signal(SIGTTOU, SIG_IGN); 
    if (tcsetpgrp(STDIN_FILENO, getpid()) == -1) { 
     printf(EXEC_ERROR, "Error in tcsetpgrp"); 
    } 
} 

ご協力いただきまして誠にありがとうございます。

ありがとうございました。

+1

なぜ、子供Aは死ぬのですか?プロセスが終了したので、次に、stdinから読み込む次の子Bは、EOFを取得して終了する必要があります。さて、これは起こらないので、Aが書き込み、Bが読み取りを行うパイプの書き込み終了は閉じられない可能性があります。子プロセスをフォークした後、メインプロセス(および該当する場合はそれ以外のすべてのプロセス)で書き込み終了を適切に閉じますか?残念ながら、あなたはコードのその部分を表示しません。 – Ctx

+0

はい、子Aは作業を終了し、正常終了します。私はパイプが正しく閉鎖されていると確信しています。私はコードのその部分を追加したいですが、それは非常に巨大であり、割り当ての一部です。私はここにどれくらいポストできるのか分かりません。 – Shubs

+0

システム環境では、プロセスaが終了した後にプロセスb(straceを使用)をトレースします。それはどこに掛かっていますか? – Ctx

答えて

0

パイプに使用されているFileDescriptorsが正しく閉じられていないため、実際には間違っていました。 @Ctxを指摘し、コメントを通じて良い提案をしてくれてありがとう。

for (i = 0; i < 2 * NoOfPipes; i++) 
    close(pipefds[j]); //should have been "i". 

私は "for"のコードを見落として、それを当然と考えていました。

関連する問題