mysleep

                                                       mysleep
普通版本的mysleep:
1、 main函数调用mysleep函数,后者调用sigaction注册了SIGALRM信号的处理函数handler。 
2、调用alarm(time)设定闹钟。 
3、调用pause等待,内核切换到别的进程运行。 
4、time秒之后,闹钟超时,内核发SIGALRM给这个进程。 
5、从内核态返回这个进程的用户态之前处理未决信号,发现有SIGALRM信号,其处理函数是handler。 
6、切换到用户态执行handler函数,进入handler函数时SIGALRM信号被自动屏蔽, 从handler函数返回时SIGALRM信号自动解除屏蔽。然后自动执行系统调用sigreturn再次进入 内核,再返回用户态继续执行进程的主控制流程(main函数调用的mysleep函数)。 
7、pause函数返回-1,然后调用alarm(0)取消闹钟,调用sigaction恢复SIGALRM信号以前的处理 动作。
(1)普通版本mysleep代码如下: 
  
#include<stdio.h>                                                       
   #include<signal.h>
   #include<unistd.h>
 void handler(int signum)
  {}       
  int mysleep(int time)
   {
      struct sigaction act,oact;
        act.sa_handler=handler;
        act.sa_flags=0;
       sigset_t sa_mask;
     sigemptyset(&sa_mask);
       sigaction(SIGALRM,&act,&oact);
       alarm(time);
     pause();     
       int ret=alarm(0);
      sigaction(SIGALRM,&act,NULL);
       return  ret;
   }           
  int main()
 {   
    while(1)
      {
     mysleep(3);
          printf("I am sleep,I will sleeping 3 second\n");
      }
      return 0;
       
  }   

(2)规避竞态mysleep
 
#include<stdio.h>   
 #include<signal.h>   
  #include<unistd.h>   
  #include<stdlib.h>   
  #include<sys/types.h>                                                   
  int sigsuspend(const sigset_t *sigmask);
  void  handler(int signum)
  {}                   
 int mysleep(int time)
   {                   
   struct sigaction act,oact;
   sigset_t newmask,oldmask,suspmask;
  act.sa_handler=handler;
      act.sa_flags=0;
     sigset_t sa_mask;
    sigemptyset(&sa_mask);
   sigaction(SIGALRM,&act,&oact);
   sigemptyset(&newmask);
   sigaddset(&newmask,SIGALRM);
  sigprocmask(SIG_BLOCK,&newmask,&oldmask);//屏蔽信号SIGALRM
   alarm(time);         
     suspmask=oldmask;         
      sigdelset(&suspmask,SIGALRM);
     sigsuspend(&suspmask);                                                                            
     int ret=alarm(0);         
     sigaction(SIGALRM,&act,NULL);
      sigprocmask(SIG_SETMASK,&oldmask,NULL);
    return  ret;               
  }                                                             
  int main()                     
  {                         
   while(1)                 
     {                     
    mysleep(3);             
        printf("I am sleep,I will sleeping 3 second\n");
     }                     
     return 0;                                         
 }     
       
     虽然两个mysleep运行的结果目前表面上都是一样的,但 系统运⾏的时序(Timing)并不像我们写程序时所设想的那样。在普通版本中,虽然alarm(time)紧接着的下⼀行就是pause(),但是无法保证pause()一定会在调用alarm(time)之后的time秒之内被调用。 被切换后,若触发SIGALRM信号,信号会立即递达当该进程切回来的时候,接收不到SIGALRM信号,不会再次接收到该信号,线程一直处于挂起状态,得不到激活。在规避竞态版本下,对SIGALRM信号进行了屏蔽,被切出去之后,该信号也不会被递达。因为是原语操作,取消屏蔽字后 ,程序正常激活。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值