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

Linux 下计时方式

2014-04-02 10:27 375 查看
http://blog.chinaunix.net/uid-12461657-id-3183111.html

1. 低精度计时

sleep 和 usleep :

sleep(int x) 系统调用,让进程等待x秒钟。其精度以秒为单位的。

usleep( int x)系统调用,让进程等待x 纳秒,但实际其精度一般是10ms,再低的达不到。

这两个函数的优点是简单。

select:

int select(intnfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,

struct timeval *timeout);

可 以通过select调用,传递timeout时间,来获取和sleep或usleep类似的效果。select函数调用比sleep和usleep复杂得 多,有人自作聪明的认为sleep/usleep精度不够,使用select替代usleep。可惜select的精度和usleep一样,都是在10ms这个级别的。

2. 高精度计时

2.1 原始办法 (忙等)

struct timespec now ;

clock_gettime(CLOCK_REALTIME,&now);

now.tv_sec += 需要等待的秒数;

now.tv_nsec +=需要等待的纳妙数;

while(1){

struct timespec t;

clock_gettime(CLOCK_REALTIME, &t);

if(t.tv_sec > now.tv_sec || t.tv_sec == now.tv_sec && t.tv_nsec > now.tv_nsec)break;

}

2.2 计时器 (timer_create)

void ticker2(union sigval v)

{

//v.sival_int为下面的tmcreate2传递的id

时钟处理函数

}

int tmcreate2(int microsec, int id)

{

timer_t tid;

struct sigevent se;

struct itimerspec ts, ots;

memset(&se,0,sizeof(se));

se.sigev_notify = SIGEV_THREAD;

se.sigev_notify_function = ticker2;

se.sigev_value.sival_int = id;

if(timer_create(CLOCK_MONOTONIC, &se, &tid) < 0){

perror("timer_creat");

return -1;

}

ts.it_value.tv_sec = 3;

ts.it_value.tv_nsec = 0;

ts.it_interval.tv_sec = 0;

ts.it_interval.tv_nsec = microsec*1000; //纳妙级

if(timer_settime(tid, TIMER_ABSTIME, &ts, &ots) < 0){

perror("timer_settime");

return -1;

}

return 0;

}

编译时需要加-lrt:gcc xxx.c -lrt

timer_create实际上调用的是rdrtc指令,因此精度和CPU的频率有关。这应该是应用层所能达到最高级别精度的时钟了。其缺点是不够灵活,定时器一旦创建就定期的调用处理函数,不能像usleep需要的时候调用一次,等待一次就结束了。

2.3 pthread_cond_timedwait

实验表明这个函数的精度可以达到微妙级以下,估计和timer_create的级别差别不多了。

int pthread_cond_timedwait(pthread_cond_t *restrictcond,

pthread_mutex_t *restrictmutex,

const struct timespec *restrictabstime);

其中最后一个参数是预期超时时间。

pthread_cond_timedwait一般使用方法为:

struct timespec expire;

clock_gettime(CLOCL_REALTIME,&expire); //获取当前系统时间

expire.tv_sec += 等待秒数;

expire.tv_nsec +=等待纳妙数;

pthread_cond_timedwait(..., &expire);

用pthread_cond_timedwait等待的线程还可以通过pthead_cond_signal唤醒,比较灵活。因此如果对精度有要求的话可以用pthread_cond_timedwait替代usleep函数。

3 内核计时器 (timer)

这个计时器只能在内核模块中使用。其精度为jifferies的精度,一般是1ms(HZ为1000)到5ms(HZ为200)。

总的来说,timer的用法还是很简单的。主要需要定义一个timer_list变量timer、

先初始化timer

init_timer(&timer);

then 对timer的相关参数赋值:

timer.function = fun;

timer.expires = jiffies + TIMER_DELAY;

add_timer(&timer);

在定时器时间到的时候,会执行fun,如果继续定时,可以通过

在fun中执行

mod_timer(&timer, jiffies + TIMER_DELAY);

在不需要的时候通过调用

del_timer(&timer);

删除定时器。

除了这个定时器外,另有hrtimer,精度更高,参考

http://www.ibm.com/developerworks/linux/library/l-timers-list/index.html

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