今天在公司代码中看到了使用select函数的超时功能作定时器的用法,便整理了如下几个Linux下的微秒级别的定时器。在我的Ubutu10.10 双核环境中,编译通过。

/*
* @FileName: test_sleep.c
* @Author: wzj
* @Brief:
*
*
* @History:
*
* @Date: 2012年02月07日星期二22:20:00
*
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<sys/time.h>
#include<errno.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/select.h>


int main(int argc, char **argv)
{
unsigned int nTimeTestSec = 0;
unsigned int nTimeTest = 0;
struct timeval tvBegin;
struct timeval tvNow;
int ret = 0;
unsigned int nDelay = 0;
struct timeval tv;
int fd = 1;
int i = 0;
struct timespec req;

unsigned int delay[20] =
{500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0};
int nReduce = 0; //误差

fprintf(stderr, "%19s%12s%12s%12s\n", "fuction", "time(usec)", "realtime", "reduce");
fprintf(stderr, "----------------------------------------------------\n");
for (i = 0; i < 20; i++)
{
if (delay[i] <= 0)
break;
nDelay = delay[i];
//test sleep
gettimeofday(&tvBegin, NULL);
ret = usleep(nDelay);
if(ret == -1)
{
fprintf(stderr, "usleep error, errno=%d [%s]\n", errno, strerror(errno));
}
gettimeofday(&tvNow, NULL);
nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;
nReduce = nTimeTest - nDelay;

fprintf (stderr, "\t usleep %8u %8u %8d\n", nDelay, nTimeTest,nReduce);

//test nanosleep
req.tv_sec = nDelay/1000000;
req.tv_nsec = (nDelay%1000000) * 1000;

gettimeofday(&tvBegin, NULL);
ret = nanosleep(&req, NULL);
if (-1 == ret)
{
fprintf (stderr, "\t nanousleep %8unot support\n", nDelay);
}
gettimeofday(&tvNow, NULL);
nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;
nReduce = nTimeTest - nDelay;
fprintf (stderr, "\t nanosleep %8u %8u %8d\n", nDelay, nTimeTest,nReduce);

//test select
tv.tv_sec = 0;
tv.tv_usec = nDelay;

gettimeofday(&tvBegin, NULL);
ret = select(0, NULL, NULL, NULL, &tv);
if (-1 == ret)
{
fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno));
}

gettimeofday(&tvNow, NULL);
nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;
nReduce = nTimeTest - nDelay;
fprintf (stderr, "\t select %8u %8u %8d\n", nDelay, nTimeTest,nReduce);

//pselcet
req.tv_sec = nDelay/1000000;
req.tv_nsec = (nDelay%1000000) * 1000;

gettimeofday(&tvBegin, NULL);
ret = pselect(0, NULL, NULL, NULL, &req, NULL);
if (-1 == ret)
{
fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno));
}

gettimeofday(&tvNow, NULL);
nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;
nReduce = nTimeTest - nDelay;
fprintf (stderr, "\t pselect %8u %8u %8d\n", nDelay, nTimeTest,nReduce);

fprintf (stderr, "--------------------------------\n");

}

return 0;
}


老大建议我们在对精度要求较高的情况下使用select()作为定时器,最大的好处就是不会影响信号处理,线程安全,而且精度能得到保证。在这个实验中,当时间延时时间较长时,select和pselect表现较差,当时间小于1毫秒时,他们的精确度便提高了,表现与usleep、nanosleep不相上下,有时精度甚至超过后者。


更多相关文章

  1. 以编程方式将位置模式更改为高精度Android
  2. 1563: 高精度加法

随机推荐

  1. 处理PHP strtotime的BUG
  2. php array_filter函数的使用(详解)
  3. 如何用PHP获取当前页面完整URL地址
  4. 区别PHP中new self() 和 new static()
  5. php round函数的实际应用(附示例)
  6. PHP自定义函数xmlToArray的实例解析
  7. 在php 中使用PDO MySQL的扩展
  8. substr函数在php中截取部分字符串(附详解)
  9. php中Date函数和时间戳函数及它们之间格
  10. 集结php常用前端语法