分类: LINUX
2012-04-20 14:05:13
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_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