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

Linux下的微秒级定时器: usleep, nanosleep, select, pselect

2016-07-27 18:04 731 查看

Linux下的微秒级定时器: usleep, nanosleep, select, pselect

标签: linuxnulldelaystructdate
2012-02-07 23:29 4979人阅读 评论(0) 收藏 举报


分类:
Linux 系统编程(26)


版权声明:本文为博主原创文章,未经博主允许不得转载。

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

[cpp] view plain copy

/*

* @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 %8u not 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不相上下,有时精度甚至超过后者

-------------------------------------------------------------------------------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: