web-dev-qa-db-ja.com

fork()とシグナルがプロセスに配信される方法

私は、C fork()の子プロセスから作成したプログラムを作成しました。どちらのプロセスも終了しません。コマンドラインからプログラムを起動し、control-cを押すと、どのプロセスが割り込み信号を受信しますか?

13
Neil Locketz

試して見てみませんか?これは signal(3) を使用して親プロセスと子プロセスの両方でSIGINTをトラップし、プロセスが到着したときにプロセスを識別するメッセージを出力する簡単なプログラムです。

_#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void parent_trap(int sig) {fprintf(stderr, "They got back together!\n");}
void child_trap(int sig) {fprintf(stderr, "Caught signal in CHILD.\n");}
int main(int argc, char **argv) {
    if (!fork()) {
        signal(SIGINT, &child_trap);
        sleep(1000);
        exit(0);
    }
    signal(SIGINT, &parent_trap);
    sleep(1000);
    return 0;
}
_

それを_test.c_と呼びましょう。これで実行できます:

_$ gcc test.c
$ ./a.out
^CCaught signal in CHILD.
They got back together!
_

端末で生成された割り込み信号は、アクティブプロセスグループに配信されます。ここには、親と子の両方が含まれます。 _child_trap_と _parent_trap_ の両方が押されたときに実行されたことがわかります Ctrl-C

forkとPOSIXのシグナル間の相互作用についての長い議論 があります。ここで最も重要な部分は次のとおりです。

Fork()の後にプロセスグループに送信されるシグナルは、親と子の両方に配信される必要があります。

また、一部のシステムは、特にfork()の時刻に非常に近くに信号が到達した場合、正確に正しく動作しない可能性があることにも注意しています。これらのシステムの1つを使用しているかどうかを判断するには、おそらくコードを読み取るか、多くの運を必要とするでしょう。これは、個々の試行でやり取りがゼロになる可能性が低いためです。

その他の便利な点は次のとおりです。

  • 手動で生成されて(おそらく kill を使用して)個別のプロセスに送信されたシグナルは、そのプロセスにonlyで配信されます。それは親または子です。
  • シグナルハンドラーがプロセス間で実行する順序は定義されていないため、どちらを先に実行するかに依存することはできません。
  • 割り込みハンドラを定義しない場合(またはシグナルを明示的に無視する場合)、両方のプロセスはSIGINTコード(デフォルトの動作)で終了します。
  • 1つが致命的ではないシグナルを処理し、もう1つが処理しない場合、ハンドラーがないものは終了し、もう1つは続行します。
20
Michael Homer