在学习sigsuspend()函数时存在一些迷惑,并不太理解书上所叙述的内容。最终,结合网上资源对该函数慢慢有了一点理解,记录下来,以备以后补充。
在《UNIX环境高级编程》中该函数的提出是在解除信号屏蔽(这里以SIGINT为例)时,信号立即发生,没有等待到pause函数执行的情况下。
sigset_t newmask,oldmask;
sigemptyset(&newmask);
sigaddset(&newmask,SIGINT);
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0){
err_sys("SIG_BLOCK error");
}
...
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0){
err_sys("SIG_SETMASK error");
}
//------------>此处正好接受并处理SIGINT信号(与内核如何实现信号有关)
pause();
这样如果后面不再收到信号,那么pause函数就一直挂起。
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
返回值:-1,并将error设置为EINTR(与pause函数返回值相同)
进程的信号屏蔽字设置为sigmask指向的值。在捕捉到一个信号或发生了一个会终止该进程的信号前,该进程被挂起(像pause函数一样)。
等到捕捉到信号,并从该信号的处理函数返回,sigsuspend函数才返回,并将该进程的信号屏蔽字设置为调用sigsuspend前。
sigsuspend()函数相当于将信号的产生与pause函数同时进行,接收到信号后会停止挂起。(不再会出现先产生信号后再调用pause的情况)
以下是在实现sleep函数中的应用:
//没有使用sigsuspend()
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
void del_func()
{
}
unsigned int mySleep(unsigned int seconds){
int ret;
struct sigaction act,oldact;
act.sa_handler = del_func;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
ret = sigaction(SIGALRM,&act,&oldact);
if(ret == -1){
perror("sigaction error");
exit(-1);
}
alarm(seconds);
//----------------------------------->如果此处该进程被cpu挂起,当定时结束发送SIGALRM信号,后面的pause不能接收到(概率极小,但是不可以不考虑)
ret = pause();
if(ret==-1&&errno == EINTR){
printf("pause success\n");
}
ret = alarm(0);
sigaction(SIGALRM,&oldact,NULL);
return ret;
}
int main()
{
while(1){
printf("======\n");
mySleep(3);
}
return 0;
}
=========================================================
//使用sigsuspend()函数
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
void del_func()
{
}
unsigned int mySleep(unsigned int seconds){
int ret;
struct sigaction act,oldact;
sigset_t newmask,oldmask,waitmask;
unsigned int unslept;
act.sa_handler = del_func;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
ret = sigaction(SIGALRM,&act,&oldact);
if(ret == -1){
perror("sigaction error");
exit(-1);
}
sigemptyset(&newmask);
sigaddset(&newmask,SIGINT);
sigprocmask(SIG_BLOCK,&newmask,&oldmask);
alarm(seconds);
waitmask = oldmask;
sigsuspend(&waitmask);
unslept = alarm(0);
sigaction(SIGALRM,&oldact,NULL);
sigprocmask(SIG_SETMASK,&oldmask,NULL);
return unslept;
}
int main()
{
while(1){
printf("======\n");
mySleep(3);
}
return 0;
}
原文地址:https://www.cnblogs.com/dog-pi/p/10104297.html