Linux提供给我们的定时器

timerfd_createtimerfd_settime 是 Linux 提供的用于创建和管理定时器的系统调用,属于 timerfdAPI 的一部分。它们允许用户空间程序通过文件描述符来使用内核定时器,非常适合需要高精度定时或与 I/O 多路复用(如 selectpollepoll)结合使用的场景。

1.timerfd_create

功能:创建一个定时器对象,并返回一个与之关联的文件描述符。

复制代码
#include <sys/timerfd.h>

int timerfd_create(int clockid, int flags);

参数

clockid 指定定时器使用的时钟类型
CLOCK_REALTIME 系统实时时钟(可受系统时间调整影响
CLOCK_MONOTONIC 单调递增时钟,不受系统时间调整影响
CLOCK_BOOTTIME CLOCK_MONOTONIC 类似,但包括系统挂起时间
flags 控制定时器的行为
TFD_NONBLOCK 设置文件描述符为非阻塞模式
TFD_CLOEXEC 设置文件描述符为 close-on-exec(执行 exec 时自动关闭)

返回值

  • 成功:返回一个文件描述符(用于后续操作)。

  • 失败:返回 -1,并设置 errno

2. timerfd_settime

**功能:**启动、停止或修改定时器的设置。

函数原型:

cpp 复制代码
#include <sys/timerfd.h>

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

参数:

fd:timerfd_create 返回的文件描述符。

flags:控制定时器的行为,常见选项:

  • 0:默认行为。

  • TFD_TIMER_ABSTIME:将 new_value.it_value 解释为绝对时间(而非相对时间)。

new_value:指向 struct itimerspec 结构体,用于设置定时器的初始值和间隔值。

cpp 复制代码
struct itimerspec {
    struct timespec it_interval;  // 定时器的间隔时间
    struct timespec it_value;     // 定时器的初始到期时间
};

struct timespec {
    time_t tv_sec;   // 秒
    long   tv_nsec;  // 纳秒
};
  • 如果 it_value 的两个字段都为 0,则停止定时器。

  • 如果 it_interval 的两个字段都为 0,则定时器只触发一次。

old_value:指向 struct itimerspec 结构体,用于返回之前的定时器设置(可以为NULL)。

返回值

成功:返回 0。

失败:返回 -1,并设置 errno。

示例:

cpp 复制代码
#include <sys/timerfd.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

int main() {
    // 创建定时器
    int fd = timerfd_create(CLOCK_MONOTONIC, 0);
    if (fd == -1) {
        perror("timerfd_create");
        exit(EXIT_FAILURE);
    }

    // 设置定时器:1秒后首次触发,之后每2秒触发一次
    struct itimerspec new_value;
    new_value.it_value.tv_sec = 1;   // 初始到期时间:1秒
    new_value.it_value.tv_nsec = 0;
    new_value.it_interval.tv_sec = 2; // 间隔时间:2秒
    new_value.it_interval.tv_nsec = 0;

    if (timerfd_settime(fd, 0, &new_value, NULL) == -1) {
        perror("timerfd_settime");
        close(fd);
        exit(EXIT_FAILURE);
    }

    printf("定时器已启动,每2秒触发一次\n");

    // 读取定时器事件
    while (1) {
        uint64_t expirations;
        ssize_t s = read(fd, &expirations, sizeof(expirations));
        if (s != sizeof(expirations)) {
            perror("read");
            close(fd);
            exit(EXIT_FAILURE);
        }
        printf("定时器触发,次数:%lu\n", expirations);
    }

    close(fd);
    return 0;
}

关键点

  • 定时器精度:timerfd 使用纳秒级精度,适合高精度定时需求。

  • 与 I/O 多路复用结合:可以将 timerfd 的文件描述符添加到 epoll 或 select 中,实现定时器与其他 I/O 事件的统一处理。

  • 资源释放:使用完毕后,应调用 close(fd) 关闭文件描述符。

适用场景

  • 周期性任务调度。

  • 超时机制(如网络请求超时)。

  • 高精度定时任务(如多媒体播放、游戏循环)。

相关推荐
Yoyo25年秋招冲冲冲6 分钟前
【亲测可用】ubuntu系统下安装Openclaw+配置飞书
linux·ubuntu·ai·飞书·openclaw
你好,帅哥23 分钟前
openssl ,msys2 ,交叉编译
linux·运维·服务器
计算机安禾33 分钟前
【Linux从入门到精通】第36篇:DNS服务探秘——自己搭建一个内网DNS
linux·运维·servlet
2023自学中41 分钟前
make clean 与 make distclean
linux·嵌入式
BenD-_-1 小时前
CVE-2026-31431 Copy Fail:Linux 内核本地提权漏洞风险与缓解
linux·网络·安全
Web极客码1 小时前
2026年Linux VPS安全加固清单:SSH、防火墙与审计就绪配置
运维·服务器·数据库
无敌的黑星星1 小时前
Java8 CompletableFuture 实战指南
linux·前端·python
星恒讯工业路由器2 小时前
配网自动化多网融合应用解决方案
运维·自动化
前端技术2 小时前
03_网络层与IP编址:理解网络寻址的核心逻辑
服务器·网络·php
智慧物业老杨2 小时前
智慧物业收费系统的数智化落地实践:从人工硬扛到自动化闭环
运维·自动化