宝塔服务器面板,一键全能部署及管理,送你10850元礼包,点我领取

通过更改进程的信号掩码,可以阻止或取消阻止选定的信号。 使用该技术,可以保护不想被信号中断的代码边界区域。 如果用一个信号解除阻止,然后pause等待以前被阻止的信号发生,怎么办? 假设信号时SIGINT,实现这一点的不正确方法之一如下。

sigset_tnewmask,oldmask;

sigemptyset 新掩码;

sigaddset 新掩码,SIGINT );

/* blocksigintandsavecurrentsignalmask */if sigprocmask SIG _ block,newmask,oldmask )0) ) )。

ERR_sysSIG_blockerror );

/* criticalregionofcode */if sigprocmask SIG _ setmask,oldmask,NULL )0) ) ) )。

ERR_sysSIG_setmaskerror );

/*窗口is open * /

pause ; /*waitforsignaltooccur*/

/*连续处理* /

如果在信号被阻止时发送到进程,则信号的传递将推迟,直到阻止被解除。 对于APP应用程序来说,此信号似乎发生在取消阻止SIGINT和pause之间。 如果发生这种情况,或者解除阻止的时间点与pause之间确实发生了信号,就会发生问题。 因为我们可能看不到这个信号,所以从这个意义上说,在这个时间窗口解除阻止和pause之间)发生的信号将会丢失,pause将永远被阻止。

要解决这个问题,必须用一个原子操作恢复信号屏蔽字,然后使过程休眠。 此功能由sigsuspend函数提供。

#includesignal.h

int sigsuspend 常数符号_ t *符号);

返回值:-1,将错误设置为EINTR

将进程的信号掩码设置为sigmask指向的值。 该进程挂起,直到收到捕获信号或终止该进程的信号。 如果捕获到信号并从信号处理程序返回,则返回sigsuspend,并将进程的信号掩码设置为调用sigsuspend之前的值。

#includeunistd.h

#includesignal.h

#includestdio.h

语音处理程序intsig )//信号处理程序

{

ifSIG==sigint ) ) ) )。

打印sigint SIG );

ELSEifSIG==SIGquit ) ) )。

打印机sigquitsig );

else

打印机SIG usr1SIG );

}

intmain ) )

{

sigset_tnew,old,wait; //三个信号集

structsigactionact;

act.sa_handler=handler;

sigemptysetact.sa_mask;

act.sa_flags=0;

sigactionsigint,act,0 ); 可以捕捉到SIGINT/SIGQUIT/SIGUSR1这3个信号

sigactionSIGquit,

 &act, 0);

    sigactionSIGUSR1, &act, 0);

   

    sigemptyset&new);

    sigaddset&new, SIGINT);  //SIGINT信号加入到new信号集中

    sigemptyset&wait);

    sigaddset&wait, SIGUSR1);  //SIGUSR1信号加入wait

    sigprocmaskSIG_BLOCK, &new, &old);       //将SIGINT阻塞,保存当前信号集到old中

   

    //临界区代码执行    

  

    ifsigsuspend&wait) != -1)  //程序在此处挂起;用wait信号集替换new信号集。即:过来SIGUSR1信  号,阻塞掉,程序继续挂起;过来其他信号,例如SIGINT,则会唤醒程序。执行sigsuspend的原子操作。注意:如果“sigaddset&wait, SIGUSR1);”这句没有,则此处不会阻塞任何信号,即过来任何信号均会唤醒程序。

        printf”sigsuspend error”);

    printf”After sigsuspend”);

    sigprocmaskSIG_SETMASK, &old, NULL);

    return 0;

}

sigsuspend的原子操作是:

(1)设置新的mask阻塞当前进程上面是用wait替换new,即阻塞SIGUSR1信号)

(2)收到SIGUSR1信号,阻塞,程序继续挂起;收到其他信号,恢复原先的mask即包含SIGINT信号的)。

(3)调用该进程设置的信号处理函数程序中如果先来SIGUSR1信号,然后过来SIGINT信号,则信号处理函数会调用两次,打印不同的内容。第一次打印SIGINT,第二次打印SIGUSR1,因为SIGUSR1是前面阻塞的)

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

 

sigsuspend的另一种应用是等待一个信号处理程序设置一个全局变量,下面的这个程序用于捕捉中断信号和退出信号。但是只是希望在捕捉到退出信号的时候,才唤醒主例程

 

int quitflag;

 

void sig_intint signo){

 

    ifsigno == SIGINT){

 

        printf”\n interrupt \n”);

 

}

 

//当收到退出信号的时候,全局变量置为1

 

    else ifsigno == SIGQUIT){

 

        quitflag == 1;

 

    }

 

}

 

 

 

void suspend_function){

 

sigset_t newmask,oldmask,zeromask;

 

//设置中断和退出的信号处理。

 

    signalSIGINT,sig_int);

 

    signalSIGQUIT,sig_int);

 

    sigemptyset&zeromask);

 

    sigemptyset&newmask);

 

    sigaddset&newmask,SIGQUIT);

 

    sigprocmaskSIG_BLOCK,&newmask,&oldmask);

 

    whilequitflag == 0)

 

        sigsuspend&zeromask);

 

    quitflag=1;

 

    sigprocmaskSIG_SETMASK,&oldmask,NULL);

 

    exit0);

 

}

 

程序结果如下:

 

转载于:https://www.cnblogs.com/zhanghongfeng/p/9153060.html