7

私は C で基本的なシェルをコーディングしており、現在、子プロセスの一時停止に取り組んでいます。

シグナルハンドラーは正しく、子プロセスは一時停止していると思いますが、その後、端末は親プロセスに戻るはずですが、それは起こっていません。

子は中断されていますが、私のシェルは入力または出力を登録していません。tcsetpgrp() は役に立たないようです。

SIGTSTP のシェル コードのシグナル ハンドラは次のとおりです。

void suspend(int sig) {
    pid_t pid;
    sigset_t mask;
    //mpid is the pgid of this shell.
    tcsetpgrp(STDIN_FILENO, mpid);
    tcsetpgrp(STDOUT_FILENO, mpid);
    sigemptyset(&mask);
    sigaddset(&mask, SIGTSTP);
    sigprocmask(SIG_UNBLOCK, &mask, NULL);
    signal(SIGTSTP, SIG_DFL);
    //active.pid is the pid of the child currently in the fg.
    if (active.pid != 0) {
        kill(active.pid, SIGTSTP);
    }
    else{
        //if this code is being run in the child, child calls SIGTSTP on itself.
        pid = getpid();
        if (pid != 0 && pid != mpid){
            kill(pid, SIGTSTP);
        }
    }
    signal(SIGTSTP, suspend);
}

誰が私が間違っているのか教えてもらえますか?

子供と一緒にシェルを一時停止していますか? どうにかして stdin と stdout をシェルに戻す必要がありますか? どうすればいいですか?

ありがとう!

4

4 に答える 4

0

tcsetpgrpフォアグラウンド ジョブとは何かを指定することです。シェルがフォアグラウンドで ( なしで&) ジョブを生成する場合、新しいプロセス グループを作成し、それをフォアグラウンド ジョブにする必要があります (STDIN にあるものではなく、制御端末の)。次に、CTRL-Z を押すと、そのジョブは TSTP を取得します。シェルではなく、ジョブを中断するのは端末です。シェルは TSTP をトラップしたり、TSTP を誰にも送信したりしてはなりません。

生成されたジョブに対してのみwait()、停止したことを検出する必要があります (そして、フォアグラウンド グループを要求し直し、ジョブを内部的に一時停止としてマークします)。あなたのfgコマンドは、ジョブの pgid を再びフォアグラウンド プロセス グループにし、それに a を送信しSIGCONTて再び待機しbgます。SIGCONT

于 2012-10-01T11:33:39.813 に答える