实现sleep-mysleep

来源:互联网 发布:淘宝童装店铺起名 编辑:程序博客网 时间:2024/06/06 19:06

sleep()—程序暂停若干时间。
模拟实现sleep—mysleep.
首先要了解三个函数:alarm,sigaction,pause
①alarm
这里写图片描述
通俗来讲,alarm是一个闹钟,闹钟是在你设定的时间后叫醒你,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终止当前进程。这个函数的返回值是0(意味着闹钟准时响了) ,因为某些原因(你醒早了)闹钟提前响了,则返回的是剩下的秒数。
②sigaction(信号捕捉函数)
这里写图片描述
sigaction函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0,出错则返回- 1。
signo是指定信号的编号。若act指针非空,则根据act修改该信号的处理动作。若oact指针非 空,则通过oact传出该信号原来的处理动作。act和oact指向sigaction结构体。
③pause
这里写图片描述
库函数使调用进程(或线程)睡眠状态,直到接收到信号,要么终止,或导致它调用一个信号捕获函数。
返回值
只有当信号被抓获和信号捕捉函数返回返回。 pause ()返回-1,并将 errno 设置为 EINTR 。
代码实现:

int mysleep(int timeout)  {      struct sigaction act,oact;      act.sa_handler = myhandler;      sigemptyset(&act.sa_mask);      act.sa_flags = 0;      sigaction(SIGALRM,&act,&oact);      alarm(timeout);      pause();      int ret = alarm(0);      sigaction(SIGALRM,&oact,NULL);      return ret;  }  

但是,有漏洞存在 : 注册SIGALRM信号的处理函数,调用alarm(seconds)设定闹钟,内核调度优先级更高的进程取代当前进程执行,并且优先级更高的进程有很多个,每个都要执行很长时间seconds秒钟之后闹钟超时了,内核发送SIGALRM信号给这个进程,处于未决状态。优先级更高的进程执行完了,内核要调度回这个进程执行。SIGALRM信号递达,执行处理函数sig_alrm之后再次进入内核。返回这个进程的主控制流程,alarm(seconds)返回,调用pause()挂起等待,可是SIGALRM信号已经处理完了,还在等待

int mysleep(int timeout)  {      struct sigaction act,oact;      sigset_t newmask,oldmask,suspmask;      act.sa_handler = handler;      sigemptyset(&act.sa_mask);      act.sa_flags = 0;      sigaction(SIGALRM,&act,&oact);      sigemptyset(&newmask);      sigaddset(&newmask,SIGALRM);      sigprocmask(SIG_BLOCK,&newmask,&oldmask);      alarm(timeout);      suspmask = oldmask;      sigdelset(&suspmask,SIGALRM);      sigsuspend(&suspmask);      int ret = alarm(0);      sigaction(SIGALRM,&oact,NULL);      sigprocmask(SIG_SETMASK,&oldmask,NULL);      return ret;  }  

如有错误,感谢指正