Linux新定时器:timefd_

    timerfd是Linux为用户程序提供的一个定时器接口。这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,所以能够被用于select/poll的应用场景。

#include <sys/timerfd.h>

// 返回值:创建定时器文件描述符
int timerfd_create(int clockid, int flags);
clockid
	CLOCK_REALTIME :系统范围内的实时时钟
	CLOCK_MONOTONIC
flags
	0
	O_CLOEXEC
	O_NONBLOCK
// 用来启动或关闭有fd指定的定时器
int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);

第二个参数:struct itimerspec 
struct timespec {
               time_t tv_sec;                /* Seconds */
               long   tv_nsec;               /* Nanoseconds */
           };

           struct itimerspec {
               struct timespec it_interval;  // 之后每隔多长时间超时
               struct timespec it_value;     // 第一次超时时间
           };
// 获得定时器距离下次超时还剩下的事件
int timerfd_gettime(int fd, struct itimerspec *curr_value);

    定时器超时事件的到来时,定时器文件描述符的值将会增加,与eventfd一样,可以用read函数读取定时器文件描述符。
    最常用的做法是:将定时器文件描述符添加到epoll树中,由epoll监控该描述符事件,当事件到来时,去处理它(具体的代码见下)

#include <stdio.h>
#include <stdlib.h>

#include <sys/timerfd.h>
#include <time.h>
#include<sys/time.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <assert.h>

const int MAXNUM = 20;

int main(int argc, char *argv[])
{
    uint64_t exp;
    ssize_t s;
    int i;
	
	// 1.构建了一个定时器
    int timefd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); 
    assert(timefd != -1);
    
	// 第二个参数(new_value)的初始化
    struct itimerspec new_value;
    // 第一次到期的时间
    struct timespec now;
    int ret = clock_gettime(CLOCK_REALTIME, &now);//获取时钟时间
    new_value.it_value.tv_sec = 5;    
    new_value.it_value.tv_nsec = now.tv_nsec;
    // 之后每次到期的时间间隔
    new_value.it_interval.tv_sec = 1;
    new_value.it_interval.tv_nsec = 0;
    
    // 2.启动定时器
    ret = timerfd_settime(timefd, 0, &new_value, NULL);
    assert(ret != -1);

    printf("timer started\n");   // 定时器开启啦!

    // 3.创建epoll树
    int epollfd = epoll_create(1);  

    struct epoll_event events[MAXNUM];

    // 4.timefd定时器事件
    struct epoll_event ev;
    ev.data.fd = timefd;
    ev.events = EPOLLIN | EPOLLET;
    
    // 5.将定时器事件添加到epoll树 && 监控
    epoll_ctl(epollfd, EPOLL_CTL_ADD, timefd, &ev); 

    // 6.死循环,等待定时器事件的到来
    for (; ;) {
        /* 当定时器到时时,定时器文件描述符将会可读,epoll_wait将会返回*/
        int num = epoll_wait(epollfd, events, MAXNUM, 0);
        assert(num >= 0);

        // 处理返回的epoll事件
        for (i = 0; i < num; i++) {
            if (events[i].events & EPOLLIN) {
                //....处理其他事件

                // 处理定时器到时事件
                if (events[i].data.fd == timefd) { 
                    // 读取
                    s = read(events[i].data.fd, &exp, sizeof(uint64_t)); //需要读出uint64_t大小, 不然会发生错误
                    assert(s == sizeof(uint64_t));
                    printf("here is timer: timefd = %d\n", events[i].data.fd);
                }
            }
        }
    }

    close(timefd);
    close(epollfd);

    return 0;
}

代码运行结果

[g@ ~/test]# gcc time.c -o time -lrt
[g@ ~/test]# ./time
timer started
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
here is timer: s = 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值