日期:2014-05-16  浏览次数:20778 次

Linux下使用select实现超级定时器

在编写程序时,我们经常回用到定时器。本文讲述如何使用select实现超级时钟。使用select函数,我们能实现微妙级别精度的定时器。同时,select函数也是我们在编写非阻塞程序时经常用到的一个函数。

首先看看select函数原型如下:

int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

说明:1)select函数使用了一个结构体timeval作为其参数。

    2)select函数会更新timeval的值,timeval保持的值为剩余时间。

如果我们指定了参数timeval的值,那么在时间耗尽后,select函数便返回,基于这一点,我们可以利用select实现精确定时。

timeval的结构如下:

struct timeval{

long tv_sec;/*secons*

long tv_usec;/*microseconds*/

}

我们可以看出其精确到microseconds也即微妙。

Linux环境下可以有多种方法实现定时。

一、秒级定时器

void seconds_sleep(unsigned seconds){
	struct timeval tv;
	tv.tv_sec=seconds;
	tv.tv_usec=0;
	int err;
	do{
	   err=select(0,NULL,NULL,NULL,&tv);
	}while(err<0 && errno==EINTR);
}
二、毫秒级别定时器

void milliseconds_sleep(unsigned long mSec){
	struct timeval tv;
	tv.tv_sec=mSec/1000;
	tv.tv_usec=(mSec%1000)*1000;
	int err;
	do{
	   err=select(0,NULL,NULL,NULL,&tv);
	}while(err<0 && errno==EINTR);
}
三、微妙级别定时器

void microseconds_sleep(unsigned long uSec){
	struct timeval tv;
	tv.tv_sec=uSec/1000000;
	tv.tv_usec=uSec%1000000;
	int err;
	do{
	    err=select(0,NULL,NULL,NULL,&tv);
	}while(err<0 && errno==EINTR);
}

现在我们来编写几行代码看看定时效果吧。

#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
int main()
{
    int i;
    for(i=0;i<5;++i){
	printf("%d\n",i);
	//seconds_sleep(1);
	//milliseconds_sleep(1500);
	microseconds_sleep(1900000);
    }
}

我们的超级定时器到此就结束了。短小精悍吧,简单就好!

作者:Viidiot   微信公众号:linux-code