
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
という表示はありません。atexit
ouch
$ 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