信号が受信されると、どの例外ハンドラが最初に呼び出されますか?

信号が受信されると、どの例外ハンドラが最初に呼び出されますか?

sleep()この関数を使用するCプログラムがあるとしましょう。

プログラムが実行され、省電力モードに切り替わります。次にCtrl+を入力してcプロセスに信号を送信します。SIGINT

私たちは、aを受け取った後のデフォルトの動作がSIGINTプロセスを終了することを知っており、眠っているプロセスが無視されていない信号を受け取るたびにスリープ関数が早く返されることがわかります。

Ctrl+を入力すると、c関数sleep()が最初に返されますか、それともプロセスが最初に終了しますか?

ベストアンサー1

基本的な作業は、SIGINTドキュメント(signal(7)ここでOpenBSDから取得)に基づいてプロセスを終了することです。

These signals are defined in the file <signal.h>:

Name         Default Action       Description
SIGHUP       terminate process    terminal line hangup
SIGINT       terminate process    interrupt program

理論的には、シャットダウンのためにプロセスでより多くのコードを実行する機会を与えてはいけません。単純なリトマステストは、何が起こっているのかを示すのに役立ちます(ただし、未処理のコードの後に​​プロセスのコードが実行されなかったことを証明するものではありませんSIGINT)。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void sigint(int sig)
{
    fprintf(stderr, "got INT\n");
}

void warnexit(void)
{
    fprintf(stderr, "atexit\n");
}

int main(void)
{
    atexit(warnexit);
    //signal(SIGINT, sigint);
    fprintf(stderr, "%d\n", getpid());
    sleep(640);
    fprintf(stderr, "ouch!\n");
    return 0;
}

ハンドラーをコメントアウトしたら、プログラムを終了しsignal(...)ます。ハンドラや行が実行中であるcontrol+c という表示はありません。atexitouch

$ make sleepint
egcc -O2 -pipe    -o sleepint sleepint.c 
$ ./sleepint
31761
^C
$ 

handlerのコメントを外すと、signal(...)残りのコードにアクセスできます。

$ make sleepint
egcc -O2 -pipe    -o sleepint sleepint.c 
$ ./sleepint 
64094
^Cgot INT
ouch!
atexit
$ 

SIGINTただし、処理は実際には非常に複雑であることに注意してください。シェルやその他のプロセスには通常SIGINTハンドラがあります(それ以外の場合はシェルがシャットダウンして悪いことがあります)、キーを押すとcontrol+cフォアグラウンドプロセスグループに信号が送信されないことがあります(プログラムはターミナルをネイティブモードに切り替えることができます)たとえば、ncursescbreak()を呼び出すと、キーが表示されますETX他の殻は異なることをします。control+cまた、このフラグを使用して、さまざまなシステムコールの動作方法を変更sigaction(2)できます。SA_RESTART

おすすめ記事