mysleep与sigsuspend函数

 承接此文,建议先看这篇文章:http://blog.csdn.net/sinat_36118270/article/details/73719061
 所以可以使用这篇文章后面的几个函数实现一个简单的mysleep函数,更加深入的了解信号
 

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

void handler(int i)
{}

void mysleep(unsigned int seconds)
{
    struct sigaction act,oact;
    act.sa_handler=handler;
    act.sa_flags=0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGALRM,&act,&oact);//log SIGALRM to do handler
    alarm(seconds);//run this proc, after seconds sign a SIGALRM signal
    pause();//handle this proc,until a signal comming----SIGALRM
    alarm(0);
    sigaction(SIGALRM,&act,&oact);

}
int main()
{
    while(1){
        printf("mysleep\n");
        mysleep(5);
    }
    return 0;
}

  
  但是,若是有一个函数或者线程之类的在 alarm(seconds)后面切出去,但是alarm函数此时还在运行,此时优先级高的函数或其他信号引起的操作还在进行,但是alarm函数已经执行完很久了,但是信号还是属于未决状态。等到其他操作进行完毕,返回用户空间,SIGALRM信号递达,执⾏处理函数sig_alrm之后再次进⼊内核。返回这个进程的主控制流程,alarm(seconds)返回,调⽤pause()挂起等待。
  


  可是SIGALRM信号已经处理完了,还等待什么呢?


  出现这个问题的根本原因是系统运⾏的时序(Timing)并不像我们写程序时所设想的那样。虽然alarm(nsecs)紧接着的下⼀⾏就是pause(),但是⽆法保证pause()⼀定会在调⽤alarm(nsecs)之 后的nsecs秒之内被调⽤。由于异步事件在任何时候都有可能发⽣(这⾥的异步事件指出现更⾼优 先级的进程),如果我们写程序时考虑不周密,就可能由于时序问题⽽导致错误,这叫做竞态条件 (Race Condition)。
  所以使用sigsuspend函数代替pause,和pause⼀样,sigsuspend没有成功返回值,只有执⾏了⼀个信号处理函数之后sigsuspend才返回,返回值为-1,errno设置为EINTR。调⽤sigsuspend时,进程的信号屏蔽字由sigmask参数指定,可以通过指定sigmask来临时解除对某 个信号的屏蔽,然后挂起等待,当sigsuspend返回时,进程的信号屏蔽字恢复为原来的值,如果原来对该信号是屏蔽的,从sigsuspend返回后仍然是屏蔽的。
  

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

void handler(int i)
{}

void mysleep(unsigned int seconds)
{
    struct sigaction act,oact;
    sigset_t newmask,oldmask,changemask;
    act.sa_handler=handler;
    act.sa_flags=0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGALRM,&act,&oact);//log SIGALRM to do handler

    sigemptyset(&newmask);
    sigaddset(&newmask,SIGALRM);//add SIGALRM to block
    sigprocmask(SIG_BLOCK,&newmask,&oldmask);//block SIGALRM,copy newmask to oldmask

    alarm(seconds);//run this proc, after seconds sign a SIGALRM signal

    changemask=oldmask;
    sigdelset(&changemask,SIGALRM);//delete SIGALRM in changemask
    sigsuspend(&changemask);//wait a signal except SIGALRM
    int ret=alarm(0);
    sigaction(SIGALRM,&oact,NULL);//make SIGALRM signal back
    sigprocmask(SIG_SETMASK,&oldmask,NULL);
}
int main()
{
    while(1){
        printf("mysleep\n");
        mysleep(5);
    }
    return 0;
}

所以此时就不用担心有之前的那种情况了。
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值