实验五:实现mysleep函数

一、实验目的

学习和掌握sleep函数中alarm的调用。

二、实验要求

函数名字和原型:

                    unsigned int mysleep(unsignedint);

该函数的功能要求与UNIX的sleep函数一样。

1、使用alarm函数实现定时。

2、必须正确处理mysleep函数中的闹钟与调用者可能设置的闹钟之间的关系。例如,如何解决不同的信号处理函数的保存和恢复?如何处理调用者设置的闹钟比mysleep函数中的闹钟早响的问题?如何处理调用进程屏蔽SIGALRM信号?

3、不允许出现任何竟态条件(时间窗口)。

4、总之,mysleep的实现细节应当对调用者透明,也就是说,不论在实现mysleep函数时是否使用了alarm函数,对调用者是否以及如何使用alarm函数均不应有任何影响。

三、实验分析过程

在mysleep函数中,用sigprocmask和sigsuspend来处理调用进程屏蔽SIGALRM信号。对于mysleep函数中的闹钟与调用者可能设置的闹钟之间的关系,在mysleep中检查第一次调用alarm的返回值,如其小于本次调用alarm的参数值,则应等到上次设置的闹钟超时。如果上次设置的闹钟的超时时间大于本次设置值,则在mysleep函数返回之前,复位次闹钟,使其在上次闹钟的设定时间再次发生超时。

四、实验程序

#include "apue.h"

static void sig_sleep(int signo)

{

}

static void sig_alrm(int signo)

{     

       printf("alarming~\n");

}

unsigned int mysleep (unsigned int nsecs)

{

       structsigaction newact, oldact;

       sigset_tnewmask, oldmask, suspmask, pendmask;

       unsignedint uslept=0, already,temp,extra=0,equal=0,suspend_before_sleep=0,MASK_SIGALRM=0;

      

       /*setour handler*/

       newact.sa_handler= sig_sleep;

       sigemptyset(&newact.sa_mask);

       newact.sa_flags= 0;

       sigaction(SIGALRM,&newact,&oldact);

 

       if(sigpending(&pendmask)<0)

       {

              printf("pendmaskerror\n");

              exit(1);

       }

       if(sigismember(&pendmask,SIGALRM))

       {//thereis a SIGALRM suspend before sleep

              suspend_before_sleep= 1;

       }

 

       /*blockSIGALRM and save signal mask*/

       sigemptyset(&newmask);

       sigaddset(&newmask,SIGALRM);

       sigprocmask(SIG_BLOCK,&newmask,&oldmask);

 

       if(sigismember(&oldmask,SIGALRM))

       {//processmask SIGALRM

              MASK_SIGALRM= 1;

       }

       /*doour work*/ 

       already= alarm(nsecs);

       if(already> 0 && already < nsecs)

       {//Alarmbefore wake up;

              if(MASK_SIGALRM== 0)

              {

                     alarm(already);

                     uslept= nsecs - already;

              }

              else//屏蔽了sigalam

                     uslept= 0;

       }

       elseif(already > 0 && already > nsecs)

       {//Alarmafter wake up;

              extra= already - nsecs;

              uslept= 0;

       }

       elseif (already > 0 && already == nsecs)

              equal= 1;

              //rememberadd alarm(uslept) at the end

      

       /*waitfor any signal to be caught*/

       suspmask= oldmask;

       sigdelset(&suspmask,SIGALRM);

       sigsuspend(&suspmask);//dealwith the SIGALRM before sleep

      

       if(suspend_before_sleep== 1)

       {

              sigsuspend(&suspmask);

       }

       /*sleepwas interrupt*/

       temp= alarm(0);

      

       /*resetsignal action and mask*/

       sigaction(SIGALRM,&oldact, NULL);

       sigprocmask(SIG_SETMASK,&oldmask, NULL);

      

       /*addextra alarm*/

       if(temp== 0)

       {

              if(extra> 0)

                     alarm(extra);

              //rebuildSIGALRM

              elseif(equal == 1 || (already < nsecs && already!=0))

                     raise(SIGALRM);

       }

       elseif (temp > 0)

       {//exceptioninterrupt by other signal

              alarm(extra+ temp);//add extra alarm

              uslept+= temp;        //correct uslept

       }

       //rebuildSIGALRM

       if(suspend_before_sleep== 1 ||(MASK_SIGALRM && already < nsecs))

              raise(SIGALRM);

       return(uslept);

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值