您的位置:首页 > 运维架构 > Linux

Linux下,实现一个sleep函数

2017-07-02 10:19 411 查看

alarm函数

首先,想要实现这个sleep函数,就得先做一些铺垫知识,所以就得先了解一下alarm函数,调用alarm函数可以设定一个闹钟,也就是告诉内核(kernel)在seconds秒之后给当前进程发送一个SIGALRM信号,该信号的默认动作是终止当前进程。这个函数的返回值是0,或者离你设定闹钟时间所剩下的秒数。举个简单的例子,你订了一个30分钟的闹钟,如果你一直没被打扰,当半小时后你的闹钟响了,它就返回0值,而当你睡了20分钟时,舍友进来将你吵醒,你还想继续睡,就设定一个20分钟后响的闹钟,这时候就会返回一个10分钟,即就是在你被吵醒到你闹钟本该响之间剩下的时间了。

先通过下面的代码熟悉alarm函数

#include<stdio.h>
#include<unistd.h>

int main()
{
int count = 1;
alarm(1);
for(;1;count++)
printf("count = %d\n",count);

return 0;
}


这个理解起来也很简单,count一直++,一秒后被SIGALRM信号终止

运行结果如下。



mysleep实现

了解了alarm函数之后,下面只要搭配使用pause()即让当前进程处于挂起状态。两个函数搭配使用,就可以实现一个简单的mysleep函数了。

代码如下:

#include<stdio.h>
#include<signal.h>

void handler(int signo)
{
}

int mysleep(int second)
{
struct sigaction act,oact;
act.sa_handler = handler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);

sigaction(SIGALRM,&act,&oact);
alarm(second);
pause();
int ret = alarm(0);
sigaction(SIGALRM,&oact,NULL);
return ret;
}

int main()
{
while(1)
{
printf("Begin sleep!\n");
mysleep(3);
printf("Finish sleep!\n");
printf("\n");
}

return 0;
}


让程序每次sleep3秒。

运行结果如下:



在每次打印Begin sleep,三秒之后,就会打印一句Finish sleep。换行之后,程序又继续进行下一次sleep了。

改进后的mysleep

那么上面的mysleep函数有没有BUG呢,答案是肯定的,试想下面一个场景,当你定好一个10分钟的闹钟后,本应该10分后给你返回,结果当第九分钟时你这个进程被切出去了(任何时候进程都有可能被切出去),30分钟后将你切回来,但是你闹钟返回信号是在20分钟前的事了,那个时候你是被切出去的,并不能接受到该信号,这就导致程序崩了。那么我们就来重新审视这个问题,编写更为完善的mysleep函数。

大致的思想是这样的,我们可以屏蔽该信号,这样不管即使被切出去了,闹钟也不会返回在你这个进程不在的时候返回信号,直到你被切回来才会收到该信号,这样就有效防止了被切除后引起的程序崩溃问题。

下面是改进后的代码:

#include<stdio.h>
#include<signal.h>

void handler(int signo)
{}

int mysleep(int second)
{
struct sigaction act,oact;
sigset_t newmask,oldmask,suspmask;
act.sa_handler = handler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);

sigaction(SIGALRM,&act,&oact);
sigemptyset(&newmask);
sigaddset(&newmask,SIGALRM);
sigprocmask(SIG_BLOCK,&newmask,&oldmask);

alarm(second);

suspmask = oldmask;
sigdelset(&suspmask,SIGALRM);
sigsuspend(&suspmask);

int unslept = alarm(0);
sigaction(SIGALRM,&oact,NULL);
sigprocmask(SIG_SETMASK,&oldmask,NULL);
return (unslept);
}

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


程序的运行结果肯定是一样的,只是第二种比第一种更加完善。通过实现这个mysleep函数,可以更加清晰的理解alarm函数了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sleep-函数 alarm