zoukankan      html  css  js  c++  java
  • linux 信号处理 三 (信号集的使用)

    sigprocmask系统调用

    使用条件:

    1、有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数。这种情况是通过阻塞信号实现的。

    2、信号阻塞和忽略信号的区别。

    阻塞的概念和忽略信号是不同的。操作系统在信号被进程解除阻塞之前不会讲信号传递出去,被阻塞的信号也不会影响进程的行为,信号只是暂时被阻止传递。当进程忽略一个信号时,信号会被传递出去但进程会将信号丢弃。

    3、信号阻塞系统调用,它们的都起到阻塞的作用,它们不是协作使用的。


    功能描述:

      设定对信号屏蔽集内的信号的处理方式(阻塞或不阻塞)。


    用法:


    #include <signal.h>
    int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

    参数:

    how:用于指定信号修改的方式,可能选择有三种

    SIG_BLOCK    //将set所指向的信号集中包含的信号加到当前的信号掩码中。即信号掩码和set信号集进行或操作。

    SIG_UNBLOCK  //将set所指向的信号集中包含的信号从当前的信号掩码中删除。即信号掩码和set进行与操作。

    SIG_SETMASK  //将set的值设定为新的进程信号掩码。即set对信号掩码进行了赋值操作。

    set:为指向信号集的指针,在此专指新设的信号集,如果仅想读取现在的屏蔽值,可将其置为NULL。

    oldset:也是指向信号集的指针,在此存放原来的信号集。可用来检测信号掩码中存在什么信号。

    返回说明:

    成功执行时,返回0。失败返回-1,errno被设为EINVAL。

     1 #include <stdio.h>
     2 #include <unistd.h>
     3 #include <signal.h>
     4 #include <stdlib.h>
     5 
     6 static void sig_int(int signo)
     7 {
     8     int i;
     9     printf("caught SIGQUIT
    ");
    10     for(i=0;i<=5;i++)
    11     {
    12         printf("signal handle %d
    ",i);
    13         sleep(1);
    14     }
    15     signal(SIGQUIT, SIG_DFL);//将SIGQUIT的动作设为缺省值
    16 }
    17 int main()
    18 {
    19     sigset_t newmask;
    20     sigset_t oldmask;
    21     sigset_t pendmask;
    22     int i=0;
    23     
    24     //信号量捕捉函数,捕捉到SIGINT,跳转到函数指针sig_int处执行
    25     signal(SIGINT, sig_int);
    26     
    27     //初始化信号量集
    28     sigemptyset(&newmask);
    29     
    30     //将SIGQUIT添加到信号量集中
    31     sigaddset(&newmask, SIGQUIT);
    32     
    33     //将newmask中的SIGQUIT阻塞掉,并保存当前信屏蔽字到Oldmask
    34     sigprocmask(SIG_BLOCK, &newmask, &oldmask);
    35     printf("sigprocmask SIGQUIT finish
    ");    
    36     //休眠5秒钟,这里做说明:在5s休眠期间,任何SIGQUIT信号都会被阻塞,如果在5s内收到任何键盘的quit信号
    37     //则此时会把这些信息存在内核的队列中,等待5s结束后,可能要处理此信号。
    38     for(i=0;i<=5;i++)
    39     {
    40         sleep(1);
    41         printf("block %d
    ",i);
    42     }
    43     
    44     //检查哪些信号是悬而未决的
    45     sigpending(&pendmask);
    46     
    47     //检查SIGQUIT是否悬而未决的所谓悬而未决,是指SIGQUIT被阻塞还没有被处理
    48     if (sigismember(&pendmask, SIGQUIT))
    49     {
    50         printf("
    SIGQUIT pending
    ");
    51     }
    52     
    53     //恢复被屏蔽的信号SIGQUIT
    54     sigprocmask(SIG_SETMASK, &oldmask, NULL);
    55     
    56     /**开始处理信号,调用信号处理函数*/ 
    57     printf("SIGQUIT unblocked
    ");
    58     
    59     sleep(5);//再次休眠5秒钟
    60     
    61     return (0);
    62 
    63 }

     所谓阻塞时间为:“sigprocmask(SIG_BLOCK, &newmask, &oldmask)”设置阻塞到“sigprocmask(SIG_SETMASK, &oldmask, NULL)”解除阻塞的整个时间,当然这期间发生了信号处理函数,也将阻塞信号集中的信号。

    以上示例是Linux redhat,
    执行结果是
    $./a.out

    sigprocmask SIGQUIT finish       //信号集添加了“SIGQUIT ”信号
    block 0
    ^Ccaught SIGQUIT         //发生了信号处理函数
    signal handle 0
    signal handle 1
    ^signal handle 2          //信号处理函数过程中信号集中的信号仍然阻塞
    signal handle 3
    signal handle 4
    signal handle 5
    block 1
    ^lock 2              //信号集中的信号阻塞
    block 3
    block 4
    block 5

    SIGQUIT pending
    退出 (核心已转储)

    【sigpending系统调用】

    #include<signal.h>

    int sigpending(sigset_t *set);

    sigpending函数返回信号集,其中的各个信号对于调用进程是堵塞的而不能递送,因而也一定是未决的。该信号集通过set参数返回。

  • 相关阅读:
    0603学术诚信和职业道德
    0602第二个冲刺
    0525《构建之法》8、9、10章读后感
    0525Sprint回顾
    实验三进程调度
    解决提问的问题
    阅读《构建之法》第13-17章
    阅读:第10、11、12章
    作业5.2(封装及测试)
    作业5.1
  • 原文地址:https://www.cnblogs.com/jiangzhaowei/p/4115401.html
Copyright © 2011-2022 走看看