第二十四篇:可靠信号机制

前言

       曾经的 UNIX 系统中,信号的不可靠的。什么是不可靠?就是信号丢失呗。那什么是信号丢失?就是当系统正在处理某个事务的时候,如果收到了某个信号,但它不能及时处理这个信号,那么只能忽略掉此信号

       而在可靠信号机制中,如果发生了上述情况,则要求系统处理完当前的事务后,还能够找回丢失的那个信号。也就是说,要具备本文即将讲述的 - 信号的阻塞功能。

信号的阻塞

       系统在信号发生后,会在进程表中设置一个标志。在信号发生到进程表中设置一个标志的时间间隔之内,我们称信号是未决的。所谓信号阻塞,就是指将信号保持未决状态,直到用户将信号解除阻塞,该信号才被接收。

重要概念:信号集

       信号集是一种数据类型,它能够表述系统内所有的信号:类似位图,某位为 1 表示该位对应的信号存在(被屏蔽),反之不存在(未被屏蔽)。对此数据类型的操作需要使用下表所提供的函数来进行:

       

大致步骤

       1. 保存当前信号屏蔽集

       2. 定义新的信号屏蔽集

       3. 使新的信号屏蔽集生效

       4. 恢复原来的信号屏蔽集

       这四个步骤,所涉及到的只有一个函数:sigprocmask 函数,该函数的详细说明请参考相关文档。

代码实现

       如下示例程序首先执行上述的步骤 1 2 3( 屏蔽退出信号 ),然后挂起 5 秒钟,然后在此期间产生 3 次退出信号,再执行上述步骤 4,最后再挂起 5 秒钟:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <signal.h>
 4 
 5 // 信号处理函数( 此类函数都是无返回且形参为一个整数,该整数即为所接收到的信号 )
 6 static void sig_quit (int);
 7 
 8 int main (void) {
 9     
10     // 定义信号集
11     sigset_t newmask, oldmask, pendmask;
12 
13     // 注册退出信号处理函数
14     if (signal(SIGQUIT, sig_quit) == SIG_ERR) {
15         printf("注册信号处理函数失败\n");
16         return 1;
17     }
18 
19     // 创建一个新的信号屏蔽字
20     sigemptyset(&newmask);
21     sigaddset(&newmask, SIGQUIT);
22 
23     // 屏蔽退出信号,并将原来的信号屏蔽字保存起来。
24     if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
25         printf("屏蔽退出信号失败\n");
26         return 2;
27     }
28 
29     printf("已屏蔽退出信号\n");
30 
31     sleep(5);
32 
33     // 恢复原来的信号屏蔽字
34     printf("\n接下来恢复原来的信号屏蔽字\n");
35     if (sigprocmask(SIG_SETMASK, &oldmask, 0) < 0) {
36         printf("恢复信号屏蔽字失败\n");
37         return 2;
38     }
39 
40     sleep(5);
41 
42     return 0;
43 }
44 
45 static void sig_quit (int signo)
46 {
47     printf("捕捉到退出信号\n");
48 
49     // 将对退出信号的处理设置为关闭进程
50     if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) {
51         printf("设置退出信号处理函数失败\n");
52     }
53 }

运行测试

       

       第一次睡眠时,我发出了三次退出信号,结果只接收并处理了一次( 假如接收了两次,则第二次就会结束掉进程了。)。

       当恢复到之前的信号屏蔽字以后,我再发出退出信号,进程立刻就关闭了。

小结

       1. 可靠信号可靠之处在于可以使信号阻塞,到合适的时候再解除阻塞,接收信号。

       2. 使用 sigaction 函数实现可靠信号更加方便。

posted @ 2017-01-28 22:50  穆晨  阅读(307)  评论(0编辑  收藏  举报