sigsuspend() 用法

这个函数的用法困扰了我很久,虽然有部分原因是apue列子没看明白,但经过一番摸索也加深了我对sigsuspend的理解。
1、关于pause()和sigsuspend()函数,但是不懂他们究竟有些什么区别,在什么时候可以相互替换,什么时候又不可以呢?
简单的说, sigsuspend = unblock + pause     
sigsuspend 函数是用于需要先接触 某个信号的阻塞状态 然后等待该信号发生 这样的应用场景; 而使用 pause 在达到这样的效果时肯定是需要先 调用sigprocmask进行取消阻塞,再调用pause去等待,取消阻塞与等待两步之间有时间窗口,在信号发生在调用pause之前任意时刻的话都有可能导致pause之后再也收不到该信号,也就是永远休眠。为了解决这种情况,sigsuspend函数把这两步做成一个原子操作,这就保证不会丢失(错过)信号,也就不会发生永远休眠这种情况(根本不发生该信号时除外)。所以,建议只用sigsuspend去等待信号。
2、

#include "apue.h"

static void    sig_int(int);

int
main(void)
{
    sigset_t    newmask, oldmask, waitmask;

    pr_mask("program start: ");

    if (signal(SIGINT, sig_int) == SIG_ERR)
        err_sys("signal(SIGINT) error");
    sigemptyset(&waitmask);
    sigaddset(&waitmask, SIGUSR1);
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGINT);

   
    if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
        err_sys("SIG_BLOCK error");

   
    pr_mask("in critical region: ");

   
    if (sigsuspend(&waitmask) != -1)
        err_sys("sigsuspend error");

    pr_mask("after return from sigsuspend: ");

   
    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        err_sys("SIG_SETMASK error");

   
    pr_mask("program exit: ");

    exit(0);
}

static void
sig_int(int signo)
{
    pr_mask("\nin sig_int: ");
}
=================================================

打印出
program start:
in critical region: SIGINT
^C
in sig_int: SIGINT SIGUSR1
after return from sigsuspend: SIGINT
program exit:

注释1:pr_mask函数是打印当前的信号屏蔽字

如果按照sig_handler先返回,那么SIGINT是不该被打印出来的,因为那时屏蔽字还没有恢复,所有信号都是不阻塞的。那么是Stevens说错了么?当然没有,只是Stevens没有说请在sigsuspend的原子操作中到底做了什么?
sigsuspend的整个原子操作过程为:
(1) 设置新的mask阻塞当前进程;
(2) 收到信号,恢复原先mask;
(3) 调用该进程设置的信号处理函数;
(4) 待信号处理函数返回后,sigsuspend返回。

解释:
在调用sigsuspend之前只有SIGINT被阻塞,调用sigsuspend后,信号屏蔽字集被临时替换成SIGUSR1,此时可以递送SIGINT,当SIGINT发生,去执行sig_int,注意:在sig_int里会打出in sig_int: SIGINT SIGUSR1 ,是因为操作系统会自动给正在被递送的信号加入屏蔽字集里(apueP250说了正在递送的信号也是未决信号,会被添加到信号屏蔽字中),当sig_int返回,sigsuspend也将返回,此时屏蔽字就是SIGINT。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值