红联Linux门户
Linux帮助

linux timerfd定时器编程

发布时间:2016-09-17 09:56:15来源:linux网站作者:lidonghat
I、Linux中与时间相关的函数 
a、 获取当前时间,计算时间间隔;  
time(2) / time_t (秒)              ----->精度太低  
ftime(3) / struct timeb (毫秒)     ---->已被废弃  
gettimeofday(2) / struct timeval (微秒) ----->满足日常计时的需要,推荐使用。  
clock_gettime(2) / struct timespec (纳秒)     ----->精度最高,但是它系统调用的开销大。
b、时区转换与日期计算;如把纽约当地时间转换为上海当地时间;  
gmtime / localtime / timegm / mktime / strftime / struct tm
c、定时操作,比如在预定的时间执行一项任务,或者在一段延时之后执行一项任务。  
sleep、alarm、usleep         --->实现时有可能用了信号 SIGALRM,在多线程程序中处理信号是个相当麻烦的事情,应当尽量避免.  
nanosleep、clock_nanosleep   --->线程安全的,但是在非阻塞网络编程中,绝对不能用让线程挂起的方式来等待一段时间,程序会失去响应。  
*itimer、timer_*             --->用信号来 deliver 超时,在多线程程序中也会有麻烦。  
timerfd_*                    --->把时间变成了一个文件描述符,能很方便地融入到 select/poll 框架中,用统一的方式来处理 IO 事件和超时事件  
 
II、timerfd_*系列函数讲解:  
1、用到的系统时钟:  
-->CLOCK_REALTIME:代表机器上可以理解为当前的我们所常看的时间,其当time-of-day 被修改的时候而改变  
-->CLOCK_MONOTONIC:代表从过去某个固定的时间点开始的绝对的逝去时间,它不受任何系统time-of-day时钟修改的影响
2、涉及的函数:  
timerfd_create:  
@function:生成一个定时器对象;  
@param1: clockid, 填写CLOCK_REALTIME或者CLOCK_MONOTONIC,表示使用哪个时钟来标示定时器的进展;  
@param2: flags, TFD_NONBLOCK(非阻塞,read(fd)如果没有超时发生就直接返回; 默认read(fd)阻塞到超时发生时返回)  
@return: 相应的文件描述符
timerfd_settime:  
@function:启动和停止定时器;  
@param1: fd, 上个函数返回的文件描述符;  
@param2: flags, 0(相对定时器)或者TFD_TIMER_ABSTIME(绝对定时器)  
@param3: new_value, 指定第一次超时时间和间隔超时时间  
@param4: old_value, 返回此函数调用时定时器的时间设置情况(可以使用timerfd_gettime获取)  
@return: 成功返回0,失败返回-1;  
 
III、示例代码  
#include <sys/timerfd.h>  
#include <string.h>  
#include <time.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <stdint.h>        /* Definition of uint64_t */  
#define handle_error(msg) \  
do { perror(msg); exit(EXIT_FAILURE); } while (0)  
static void  
print_elapsed_time(void)  
{  
static struct timespec start;  
struct timespec curr;  
static int first_call = 1;  
int secs, nsecs;  
if (first_call) {  
first_call = 0;  
if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)  
handle_error("clock_gettime");  
}  
if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)  
handle_error("clock_gettime");  
secs = curr.tv_sec - start.tv_sec;  
nsecs = curr.tv_nsec - start.tv_nsec;  
if (nsecs < 0) {  
secs--;  
nsecs += 1000000000;  
}  
printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);  
}
int  
main(int argc, char *argv[])  
{  
struct itimerspec new_value;  
int max_exp, fd;  
struct timespec now;  
struct timespec curr;  
uint64_t exp, tot_exp;  
ssize_t s;  
/* 分别使用不同的时钟创建timerfd */  
fd = timerfd_create(CLOCK_MONOTONIC, 0);  
//fd = timerfd_create(CLOCK_REALTIME, 0);  
if (fd == -1)  
handle_error("timerfd_create");
#if 0  
/* MONOTONIC的绝对定时器 */  
if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)  
handle_error("clock_gettime");  
new_value.it_value.tv_sec = curr.tv_sec + 3;  
new_value.it_value.tv_nsec = curr.tv_nsec;  
#endif
#if 0  
/* REALTIME的绝对定时器 */  
if (clock_gettime(CLOCK_REALTIME, &now) == -1)  
handle_error("clock_gettime");  
new_value.it_value.tv_sec = now.tv_sec + 3;  
new_value.it_value.tv_nsec = now.tv_nsec;  
#endif  
/* 相对定时器 */  
bzero(&new_value, sizeof(new_value));  
new_value.it_value.tv_sec = 3;  
//if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)  
if (timerfd_settime(fd, 0, &new_value, NULL) == -1)  
handle_error("timerfd_settime");  
print_elapsed_time();  
printf("timer started\n");  
s = read(fd, &exp, sizeof(uint64_t));  
if (s != sizeof(uint64_t))  
handle_error("read");  
tot_exp += exp;  
print_elapsed_time();  
printf("read: %llu", (unsigned long long) exp);  
exit(EXIT_SUCCESS);  
}
 
本文永久更新地址:http://www.linuxdiyf.com/linux/24229.html