第十章(二) sigsuspend、system等重要信号函数的使用

函数    sigsuspend(sigset_t *mask)

    1、之前说过,更改进程的信号屏蔽字可以阻塞所选择的信号,或解除对它们的阻塞,这可以用来保护不希望由信号中断的代码临界区
    2、如果希望对一个信号解除阻塞,然后pause以等待以前被阻塞的信号发生,如何实现呢?
        若是直接  sigprocmask(); pause(); 这样可能会导致pause永久阻塞,所以可以使用此函数 sigsuspend。

    进程的信号屏蔽字设置为由 sigmask 指向的值。 在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回。并且该进程的信号屏蔽字设置为调用sigsuspend之前的值。

    此函数经常和pause相比较。
    
    这段愣是没看懂,上网查了一下:
     sigsuspend的原子操作是:

    (1)设置新的mask阻塞当前进程(用参数替换当前屏蔽字,这里的参数屏蔽字包含SIGUSR1)

    (2)收到SIGUSR1信号,阻塞,程序继续挂起;收到其他信号,恢复原先的mask(即包含SIGINT信号的)。
    
    (3)调用该进程设置的信号处理函数(程序中如果先来SIGUSR1信号,然后过来SIGINT信号,则信号处理函数会调用两次,打印不同的内容。第一次打印SIGINT,第二次打印SIGUSR1,因为SIGUSR1是前面阻塞的)

    (4)待信号处理函数返回,sigsuspend返回了。(sigsuspend将捕捉信号和信号处理函数集成到一起了)

     (一)  、  Show how to protect the code area from being interrupted by unexpected signal.

//
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void pr_mask(char *s)
{
        printf("%s  ",s);
        sigset_t set;
        if(sigprocmask(0,NULL,&set) < 0)
        {
                perror("sigprocmask");
                exit(1);
        }

        if(sigismember(&set,SIGUSR1))
                printf("SIGUSR1");
        if(sigismember(&set,SIGALRM))
                printf("SIGALRM");
        if(sigismember(&set,SIGINT))
                printf("SIGINT");
        putchar('\n');
}

void sig_int(int s)
{
        pr_mask("\nin sig_int");
}

void sig_usr(int s)
{

}

int main()
{
        sigset_t new,old,wait;

        pr_mask("program mask : ");

        if(signal(SIGINT,sig_int) == SIG_ERR)
        {
                perror("signal");
                exit(1);
        }

        if(signal(SIGUSR1,sig_usr) == SIG_ERR)
        {
                perror("signal");
                exit(1);
        }

        sigemptyset(&wait);
        sigaddset(&wait, SIGUSR1);
        sigemptyset(&new);
        sigaddset(&new, SIGINT);

        //Block SIGINT and save curret mask
        if(sigprocmask(SIG_BLOCK,&new,&old) < 0)            //在原有屏蔽字中添加SIGINT
        {
                perror("sigprocmask");
                exit(1);
        }

        //Critical region of code
        pr_mask("in critical region");                //通过结果发现现在SIGINT是应该被阻塞在外的

        //Pause, allowing all signals except SIGUSR1
        if(sigsuspend(&wait) != -1)                    //通过sigsuspend改变当前的屏蔽字为wait的值,现在我们发送SIGINT进程可以接收了
        {
                perror("sigsuspend");
                exit(1);
        }

        pr_mask("After return from suspend : ");            //结果显示,这里仍然是SIGINT被包含在内

        //reset signal mask which unblocks SIGINT

        if(sigprocmask(SIG_SETMASK,&old,NULL) < 0)
        {
                perror("sigprocmask");
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值