Linuxの下で信号blockとunblockについての小さい研究

17881 ワード

Linuxでは、あるプロセスに信号を送信すると、信号生成からプロセスに信号を受信し、対応する動作を実行するプロセスを信号の待機プロセスと呼ぶ(APUEの理解に基づいて翻訳される).ある信号がプロセスによって遮断されていない場合、プロセスがその信号に対応する動作をプログラム内でブロックすることができる.例えば、SIGUSR 1信号を受信すると、システムAPIブロッキングプログラムを用いて、ブロッキングを解除するまで、SIGUSR 1信号を受信すると、プログラムが動作する.もう一つの現実的な例を挙げます:まるで同級生が私にご飯を持ってきてくれたようですが、私は今他のことをしなければなりません.今、私はまず私の手元のことをして、私の手の上のことが完成するまで彼にご飯を持ってきます.全体の過程があまり悪くないのはこのようなことだ.
マルチスレッドと非マルチスレッドの場合を考慮した.
次に、このプログラムはusr 1を受信し、usr 2信号は2つのグローバル変数usr 1とusr 2の値を1に設定するコードを見てみましょう.メインプログラムには2つのサイクルがあり、1つ目のサイクルがusr 1信号を受信するとループから飛び出し、2つ目のサイクルがusr 1を受信すると、usr 2信号はいずれもループから飛び出します.
 1 #include<stdio.h>
2 #include<signal.h>
3 #include<unistd.h>
4
5 int flag_sigusr1 = 0;
6 int flag_sigusr2 = 0;
7
8 void sig_usr1(int signo){
9 fprintf(stdout, "caught SIGUSR1
");
10 flag_sigusr1 = 1;
11 return;
12 }
13
14 void sig_usr2(int signo){
15 fprintf(stdout, "caught SIGUSR2
");
16 flag_sigusr2 = 1;
17 return;
18 }
19
20 int main(void){
21 sigset_t newmask, oldmask;
22
23 signal(SIGUSR1, sig_usr1);
24 signal(SIGUSR2, sig_usr2);
25
26 fprintf(stdout, "first while. catch sigusr1 can break
");
27 while(1){
28 if(flag_sigusr1){
29 fprintf(stdout, "break");
30 break;
31 }
32 sleep(10);
33 }
34 flag_sigusr1 = 0;
35
36 //block SIGUSR1
37 sigemptyset(&newmask);
38 sigaddset(&newmask, SIGUSR1);
39 if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0){
40 perror("sigprocmask error");
41 }
42
43 fprintf(stdout, "first while. catch sigusr1 or sigusr2 can break
");
44 while(1){
45 if(flag_sigusr1 || flag_sigusr2){
46 fprintf(stdout, "break");
47 break;
48 }
49 sleep(10);
50 }
51
52 return 0;
53 }

最初のサイクルと2番目のサイクルの間でsigusr 1信号をブロックすることを選択したので、プログラムが2番目のサイクルに実行されると、usr 1信号がプログラムに送信されると、サイクルから飛び出しません.
マルチスレッドの場合、各スレッドは信号処理関数を共有するが、各スレッドは、ある信号をブロックするかどうかを選択することができる.
もう1つのマルチスレッドの例を見ると、サブスレッドの機能と同様に、メインスレッドがhup信号を受信すると、サブスレッドにusr 2信号が送信される.
  1 #include<stdio.h>
2 #include<signal.h>
3 #include<unistd.h>
4 #include<pthread.h>
5
6 int flag_sigusr1 = 0;
7 int flag_sigusr2 = 0;
8 int flag_sighup = 0;
9
10 void sig_usr1(int signo){
11 fprintf(stdout, "sig|caught SIGUSR1
");
12 flag_sigusr1 = 1;
13 return;
14 }
15
16 void sig_usr2(int signo){
17 fprintf(stdout, "sig|caught SIGUSR2
");
18 flag_sigusr2 = 1;
19 return;
20 }
21
22 void sig_hup(int signo){
23 fprintf(stdout, "sig|caught SIGHUP
");
24 flag_sighup = 1;
25 return;
26 }
27
28 void *thread_control_signal(void *arg){
29 sigset_t newmask, oldmask;
30 sigemptyset(&newmask);
31
32 //thread block sighup
33 sigemptyset(&newmask);
34 sigaddset(&newmask, SIGHUP);
35 if(pthread_sigmask(SIG_BLOCK, &newmask, &oldmask) < 0){
36 perror("sigprocmask error");
37 }
38
39 fprintf(stdout, "thread|first while. catch sigusr1 or sigusr2 can break
");
40 while(1){
41 if(flag_sigusr1 || flag_sigusr2){
42 fprintf(stdout, "thread|break
");
43
44 break;
45 }
46 sleep(10);
47 }
48 flag_sigusr1 = 0;
49
50 //thread block SIGUSR1
51 sigaddset(&newmask, SIGUSR1);
52 if(pthread_sigmask(SIG_BLOCK, &newmask, &oldmask) < 0){
53 perror("sigprocmask error");
54 }
55
56 fprintf(stdout, "thread|first while. catch sigusr2 can break
");
57 while(1){
58 if(flag_sigusr1 || flag_sigusr2){
59 fprintf(stdout, "break
");
60 break;
61 }
62 sleep(10);
63 }
64
65 fprintf(stdout, "thread|thread exit
");
66 return (void *)0;
67 }
68
69 int main(void){
70 sigset_t newmask;
71 pthread_t tid;
72 int signo;
73
74 //signal action
75 signal(SIGUSR1, sig_usr1);
76 signal(SIGUSR2, sig_usr2);
77 signal(SIGHUP , sig_hup);
78
79 if(pthread_create(&tid, NULL, thread_control_signal, NULL) < 0){
80 perror("create pthread failed");
81 return -1;
82 }
83
84 //main thread block sigusr1
85 sigemptyset(&newmask);
86 sigaddset(&newmask, SIGUSR1);
87 if(pthread_sigmask(SIG_BLOCK, &newmask, NULL) < 0){
88 perror("sigprocmask error");
89 }
90
91 //main thread wait sighup
92 sigemptyset(&newmask);
93 sigaddset(&newmask, SIGHUP);
94 if(sigwait(&newmask, &signo) < 0){
95 perror("sigwait failed");
96 return -1;
97 }
98 fprintf(stdout, "main|get SIGHUP
");
99
100 pthread_kill(tid, SIGUSR2);
101 pthread_kill(tid, SIGUSR2);
102 pthread_join(tid, NULL);
103
104 fprintf(stdout, "main|exit
");
105 return 0;
106 }

over~