模拟实现sleep函数——mysleep()

来源:互联网 发布:api数据接口 编辑:程序博客网 时间:2024/05/18 22:41

sleep函数原型:

#include<unistd.h>unsigned int sleep(unsigned int seconds);

什么是sleep()函数?

sleep函数,是一个常用的定时函数,在指定时间内不做任何动作,时间结束后继续执行要完成的工作。
那么,自然要使用到定时函数alarm函数

#include<unistd.h>unsigned int alarm(unsigned int seconds);

我们日常使用的sleep函数,在使用期间,不做任何动作,所以我们的myhandler也不做任何动作,只进行捕捉。那么如何使mysleep运行期间,保证该进程被挂起,不做任何动作呢?

#include<unistd.h>int pause(void);

pause函数使调⽤用进程挂起直到有信号递达。如果信号的处理动作是终止进程,则进程终
止,pause函数没有机会返回;如果信号的处理动作是忽略,则进程继续处于挂起状态,pause
不返回;如果信号的处理动作是捕捉,则调⽤用了信号处理函数之后pause返回-1,errno设置为
EINTR, 所以pause只有出错的返回值。错误码EINTR表示“被信号中断”。

准备工作已经差不多了,那我们开始模拟实现mysleep()函数吧。

#include<stdio.h>#include<unistd.h>#include<signal.h>void sig_alrm(int signo){    //nothing should to do}unsigned int mysleep(unsigned int msecs) {     struct sigaction new,old;     unsigned int unslept = 0;     new.sa_handler = sig_alrm;     sigemptyset(&new.sa_mask);     new.sa_flags = 0;     sigaction(SIGALRM,&new,&old);//注册信号处理函数     alarm(msecs);//设置闹钟     pause();     unslept = alarm(0);//清除闹钟    sigaction(SIGALRM,&old,NULL);//恢复默认信号处理动作     return unslept;}int main(){     while(1)//每隔5s打印一次    {         mysleep(5);         printf("5 seconds passed\n");    }   return 0;}/***************************************************//**********************by  peter********************//***************************************************/

Ctrl+\结束程序运行,或者ps axj | grep test,找到PID然后使用kill命令
mysleep()函数的基本功能已经实现了。细心的朋友可能已经发现了,每次的时间好像都太一样,多那么一秒半秒的,为什么呢?
如果alarm函数执行完毕后,该进程被切出去,cpu去处理了优先级更高的进程,然后再切回该进程时,有可能出现计时已经结束的场景.那么pause便会该进程一直挂起!!!!造成超过所设定的时间,如果这是一枚定时导弹,那么时间到了,导弹还没有爆炸,那如果你是工程师,你觉得现在过去拆导弹合适吗?

所以我们升级我们的武器,版本2的mysleep(),

 #include<stdio.h> #include<unistd.h> #include<signal.h>  void sig_alrm(int signo) {     //nothing should to do } unsigned int mysleep(unsigned int msecs) {     struct sigaction new,old;     sigset_t newmask,oldmak,sussem;     unsigned int unslept = 0;     new.sa_handler = sig_alrm;     sigemptyset(&new.sa_mask);     new.sa_flags = 0;     sigaction(SIGALRM,&new,&old);//注册信号处理函数     sigemptyset(&newmask);     sigaddset(&newmask,SIGALRM);     sigprocmask(SIG_BLOCK,&newmask,&oldmak);     alarm(msecs);//设置闹钟     sussem = oldmak;     sigdelset(&sussem,SIGALRM);     sigsuspend(&sussem);     unslept = alarm(0);//清除闹钟     sigprocmask(SIG_BLOCK,&oldmak,NULL);     sigaction(SIGALRM,&old,NULL);//恢复默认信号处理动作     return unslept; } int main() {     while(1)     {         mysleep(5);         printf("5 seconds passed\n");     }     return 0; }/***************************************************//**********************by  peter********************//***************************************************/

这里写图片描述