timerfd 初级笔记1

作者: | 更新日期:

几个月前我使用timerfd封装了一个定时器,使用了这么久一切正常。今天回顾一下timerfd的基础知识。

timerfd是什么

timerfd 是 Linux 为用户程序提供的一个定时器接口。

这个接口基于文件描述符,然后我们就可以和 epoll 组合做很多事了。

关于 epoll 的记录可以看看这里 epoll初级笔记1.

创建定时器

使用 timerfd_create 函数可以创建一个定时器。

#include <sys/timerfd.h>

int timerfd_create(int clockid, int flags);
int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
int timerfd_gettime(int fd, struct itimerspec *curr_value);

参数 clockid 可以是 CLOCK_MONOTONIC 或者 CLOCK_REALTIME 。
这两个参数的区别如下:

flags 参数在 linux 2.6.26 版本之后,必须为0。

之前参数可以使用 TFD_NONBLOCK 和 TFD_CLOEXEC 通过异或配置。

函数执行成功返回一个文件描述符,失败的话返回-1,错误码需要查errno。

错误码如下

设置非阻塞模式

由于timerfd_create的flags参数现在必须为0了, 所以我们必须手动设置这个FD为非阻塞模式了。

设置代码如下, 获取现有FD的参数, 然后加上 O_NONBLOCK, 最后再设置我们的FD即可。

flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags)

我这里有简单的介绍 fcntl 函数 - 简单了解linux 文件I/O.

不懂 fcntl 的人可以来这里快速了解一下这个函数的功能。

设置超时时间

创建完定时器的FD了,肯定要设置超时时间才能启动定时作用啦。

#include <sys/timerfd.h>

int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);

得到设置的时间

有时候,我们需要手动定时器时,可能需要查询上次设置的时间,这时可以使用 timerfd_gettime 函数。

#include <sys/timerfd.h>

int timerfd_gettime(int fd, struct itimerspec *curr_value);

定时器的数据结构

我们在设置时间和得到时间时,遇到了结构体 struct itimerspec, 它的结构如下。

struct timespec {
    time_t tv_sec;                /* Seconds */
    long   tv_nsec;               /* Nanoseconds */
};

struct itimerspec {
    struct timespec it_interval;  /* Interval for periodic timer */
    struct timespec it_value;     /* Initial expiration */
};

简单使用样例

//创建定时器
timer_id = timerfd_create(CLOCK_REALTIME, 0);

//设置非阻塞
flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags)

//设置超时时间
double timer_internal = 3.2;
struct itimerspec ptime_internal;
memset(&ptime_internal, 0, sizeof(ptime_internal));
ptime_internal.it_value.tv_sec = (int) timer_internal;
ptime_internal.it_value.tv_nsec = (timer_internal - (int) timer_internal) * 1000000;

timerfd_settime(timer_id, 0, &ptime_internal, NULL);

//其他操作
点击查看评论

关注公众号,接收最新消息

关注小密圈,学习各种算法

tiankonguse +
穿越