linux sigsuspend()函数解析

本文介绍了 进程的信号屏蔽字设置为sigmask指向的值。在捕捉到一个信号或发生了一个会终止该进程的信号前,该进程被挂起(像pause函数一样)。 等到捕捉到信号,并从该信号的处理函数返回,sigsuspend函数才返回,并将该进程的信号屏蔽字设置为调用sigsuspend前。sigsuspend()函数相当于将信号的产生与pause函数同时进行,接收到信号后会停止挂起。

在《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;
}
上一篇 下一篇


推荐文章

评论
说点什么吧?

发表评论

取消回复
  最新文章