![ユーザー入力から信号をキャプチャする方法は? [閉鎖]](https://linux33.com/image/149505/%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%85%A5%E5%8A%9B%E3%81%8B%E3%82%89%E4%BF%A1%E5%8F%B7%E3%82%92%E3%82%AD%E3%83%A3%E3%83%97%E3%83%81%E3%83%A3%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%EF%BC%9F%20%5B%E9%96%89%E9%8E%96%5D.png)
ユーザーにシグナル番号を入力するように要求し、ハンドラーを呼び出すプログラムを作成しようとしています。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void decide(int signo)
{
printf("I received signal\n");
}
int main()
{
int signum;
printf("Enter Signal Number:");
scanf("%d", &signum);
if(signal(signum,decide) == SIG_ERR)
{
perror("signal");
}
//pause();
printf("I hope you have a good evening!\n");
return 0;
}
しかし、シグナルハンドラをスキップして常に最後の行を印刷するようです。ハンドラを呼び出すように何を変更できますか?
答え1
これsignal
機能(おそらく名前とは異なり)信号処理動作のみを設定します。未来表示される信号:
この
signal()
機能は、信号番号を受信する3つの方法のうちの1つを選択します。シグナル 今後の処理予定。値がある場合機能SIG_DFLの場合は、デフォルトで信号を処理する必要があります。値がある場合機能SIG_IGNの場合、この信号は無視されます。そうでない場合、アプリケーションは以下を保証する必要があります。機能このシグナルが発生したときに呼び出される関数へのポインター。
あなたのプログラムは信号ハンドラを設定し、エラーがないことを確認します。素晴らしいです! - しかし、継続して別れを印刷し、すぐに終了します。この時点で、プロセス全体(信号ハンドラを含む)はもう存在しません。
環境シグナルハンドラはUnixモデルでは別々のイベントです。受付と処理信号。ハンドラが設定されると、前方に到着するすべての信号は処理のためにハンドラに送信され、プログラムの残りの部分は引き続き実行されます。一致する信号が発生しない場合、ハンドラは静かに座って何もする必要はありません。
そこはい信号が終了する前に信号を転送できる非常に小さなウィンドウです。このウィンドウは本質的にあなたの場所ですpause()
呼ぶコメントアウト - 実はほぼその程度ですこの機能の目的pause
は:
この
pause()
関数は、シグナルが渡されるまで呼び出しスレッドを中断する必要があります。これは、シグナルキャプチャー関数を実行するかプロセスを終了することです。
それ以外の場合は、マイクロウィンドウでもマイクロウィンドウでも、別の端末でハンドラを実行pause
できます。kill -XYZ $pid
私がこれを行うセッションは次のとおりです。
mwh:/tmp$ ./test
Enter Signal Number:12
I received signal
I hope you have a good evening!
mwh:/tmp$
test
他の端末でプロセスのPIDを見つけてps awx
実行しましたkill -12 9245
。プロセスはEnterを押すまで何もせずに残りますkill
。シグナルハンドラを実行すると、メッセージが印刷され返され、残りのプログラムが実行されて完了します。test
pause()
プロセスがシグナルを送信したい場合私に何らかの理由であなたもこれを行うことができます。これraise
機能これはあなたがするために生まれたものです:
この
raise()
関数はシグナルを送信する必要がありますシグナル実行中のスレッドまたはプロセスに。シグナルハンドラが呼び出されると、raise()関数はシグナルハンドラが返されるまで返すべきではありません。
だから
raise(signum);
置換がpause();
機能します。
興味深い結果を得ることができるSIGKILLや他の捕捉できない信号の特別な場合を除いて、ここではあまり役に立ちません(9と19を入力してみてください!)。ただし、シグナルとプロセスモデルがどのように機能するかを調べると、PIDを見つけるのに時間と労力を節約できます。
あなたもできます使用kill(getpid(), signum);
またはpthread_kill(pthread_self(), sig);
(正確に定義されているraise(signum)
)。