• 可靠信号机制


    前言

      曾经的 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("注册信号处理函数失败
    ");
    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("屏蔽退出信号失败
    ");
    26         return 2;
    27     }
    28 
    29     printf("已屏蔽退出信号
    ");
    30 
    31     sleep(5);
    32 
    33     // 恢复原来的信号屏蔽字
    34     printf("
    接下来恢复原来的信号屏蔽字
    ");
    35     if (sigprocmask(SIG_SETMASK, &oldmask, 0) < 0) {
    36         printf("恢复信号屏蔽字失败
    ");
    37         return 2;
    38     }
    39 
    40     sleep(5);
    41 
    42     return 0;
    43 }
    44 
    45 static void sig_quit (int signo)
    46 {
    47     printf("捕捉到退出信号
    ");
    48 
    49     // 将对退出信号的处理设置为关闭进程
    50     if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) {
    51         printf("设置退出信号处理函数失败
    ");
    52     }
    53 }

    运行测试

      

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

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

    小结

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

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

  • 相关阅读:
    cs231n.stanford.edu
    cs229.stanford.edu
    Boost circular_buffer example
    OI中一些常见实用的套路【更新中】
    用Java读取xml文件内容
    在控制台中操作MYSQL数据库步骤以及一些小问题
    java 实现对指定目录的文件进行下载
    将java项目发布到本地的linux虚拟机上
    mybatis 控制台打印出来的sql 执行结果为空 但是将sql放到mysql执行有数据
    spring mvc 拦截器
  • 原文地址:https://www.cnblogs.com/scut-fm/p/3674891.html
Copyright © 2020-2023  润新知