表題の通りです。
シグナルというものが別プロセスへの割り込みだということは理解できましたが
signal関数の定義式の意味がさっぱり分かりません。
定義式
void (*signal(int sig, void (*func)(int)))(int)
現状理解できていること
・一般的な関数ポインタについて
※ 型 (*ラベル名) (引数)が関数へのポインタ変数になり
関数のアドレスを格納するとラベル名(引数)で関数を呼び出せる。
関数ポインタについては上記の理解ですがsignal()の説明になると
「signal()は、引数がint型、返り値がvoid型の関数へのポインタを返す関数で、
引数として、int型と、int型を引数として受け取りvoid型を返り値として返す関数へのポインタを返す」
というような説明が多くどのような動きをしているか説明がなくイメージがわきません。
お手数ですがこれを理解するためにどなたか解説いただけないでしょうか。
もしくはこれを理解するための知識の何が足りなくどれを勉強すればよいか
教えていただけないでしょうか。
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/03 04:56
回答5件
0
ベストアンサー
本当に知りたいのは「signal関数はどのように動くか/何の役に立つか」ということでしょうか?
そうですね。まずはそれを知ることが出来ればいいかと思っております。
C言語signal
関数の理解には、前提知識としてOSが提供する「シグナル(Signal)」の仕組みを理解している必要があります。
詳細説明は上記で紹介したサイトに譲ります。signal
関数の動作は下記2つで説明されます:
c
1void (*signal(int sig, void (*func)(int)))(int);
- 指定したシグナル番号
sig
に対応するシグナルハンドラとして、指定した関数ポインタfunc
を登録する。(振る舞いの説明) - 直近の古いシグナルハンドラ(関数ポインタ)を返す。(戻り値の説明)
シグナルハンドラとして引数で登録/戻り値となっている関数ポインタが、質問中にある「引数がint型、返り値がvoid型の関数へのポインタ(void(*)(int)
型)」に対応します。
投稿2020/12/03 05:38
編集2020/12/03 05:41総合スコア6191
0
C
1typedef void (*sighandler_t)(int); 2sighandler_t signal(int signum, sighandler_t sighandler);
signal は関数で、引数にシグナル番号 signum とハンドラー指定すると、
そのシグナル番号のシグナルを受けた時に、そのハンドラーを呼び出します。
signal は、以前のハンドラーを返します。
C
1#include <stdio.h> // printf, fflush 2#include <signal.h> // signal, SIGINT 3#include <unistd.h> // sleep 4 5void handler1(int sig) { printf("\nhandler1: sig = %d\n", sig); } 6void handler2(int sig) { printf("\nhandler2: sig = %d\n", sig); } 7 8int main(void) 9{ 10 void (*f1)(int); 11 void (*f2)(int); 12 13 f1 = signal(SIGINT, handler1); 14 f2 = signal(SIGINT, handler2); 15 16 printf("handler1 = %p\n", handler1); 17 printf("handler2 = %p\n", handler2); 18 printf("f1 = %p\n", f1); 19 printf("f2 = %p\n", f2); 20 21 for (int i = 0; i < 30; i++) { 22 if (i == 10) signal(SIGINT, f2); 23 if (i == 20) signal(SIGINT, f1); 24 printf(" %d", i); 25 fflush(stdout); 26 sleep(1); 27 } 28}
実行例
text
1$ ./a.out 2handler1 = 0x7f98055431a9 3handler2 = 0x7f98055431d1 4f1 = (nil) 5f2 = 0x7f98055431a9 6 0 1 2 3 4^C 7handler2: sig = 2 8 5 6 7 8^C 9handler2: sig = 2 10 9 10 11 12 13^C 11handler1: sig = 2 12 14 15 16 17^C 13handler1: sig = 2 14 18 19 20 21 22 23 24 25 26^C 15$
投稿2020/12/02 17:11
総合スコア8224
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/03 04:46
2020/12/03 04:53
2020/12/03 06:28 編集
2020/12/03 07:38
0
signal
関数は、シグナルを受けたときの処理を指定します。
C
1void foo(int s){ 2 printf("シグナル %d を受けました\n",s); 3} 4 5int main(){ 6 ・・・ 7 signal(2, foo); 8 ・・・ 9}
とすると、main
実行中signal
呼び出し以降に、シグナル2(つまりCtrl-Cを押した)を受けたときにfoo
関数が呼ばれます。
この場合は、「プログラムを停止する」というシグナル2のデフォルト動作はしません。
投稿2020/12/02 06:33
総合スコア85893
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/02 06:49
2020/12/02 07:00
2020/12/02 07:47
2020/12/02 08:14
2020/12/02 16:18
2020/12/02 16:26
0
signalは、シグナル番号(変数sig)に対する割り込みハンドラー(変数func)を登録する関数です。
以下をご参考ください。
C言語でシグナルをハンドルする
投稿2020/12/02 06:01
総合スコア1095
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
void (*signal(なんたら, かんたら))(int);
これで、signal関数は、関数ポインタを返す関数って事がわかるでしょうか。
そのポインタの関数は、intを引数としたvoid型の関数ですね
んじゃ第2引数の方を。
void (*func)(int)
こいつも、intを引数に取るvoidを返す関数のポインタですね
投稿2020/12/02 05:56
総合スコア88038
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/02 06:33
2020/12/02 06:37
2020/12/02 06:47
2020/12/02 06:49
2020/12/02 06:50
2020/12/02 06:55
2020/12/02 07:35
2020/12/02 07:50
2020/12/02 08:10 編集
2020/12/02 08:55
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。