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) 关闭文件描述符。

适用场景

  • 周期性任务调度。

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

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

相关推荐
杨云龙UP4 小时前
MySQL 数据库常用备份工具对比:mysqldump、mydumper 与 XtraBackup
linux·运维·服务器·数据库·mysql·dba·备份恢复
PC2005-cloud4 小时前
从零上手 openGauss:Docker 部署 + 全场景连接教程
运维·docker·容器
独隅4 小时前
Cursor+GitOps 自动化运维实战:智能编写 Ansible 与 Terraform
运维·自动化·ansible
happymagic5 小时前
java spring boot做的jar包程序,如何实现自动运行启动
java·运维·服务器·spring boot·jar
星空你好5 小时前
AI辅助运维:开源一个内网日志监控工具
运维
风曦Kisaki5 小时前
Kubernetes(K8s)笔记Day06: 持久化存储(emptyDir,hostPath,NFS),PV 和 PVC,StorageClass存储类
linux·运维·笔记·云原生·容器·kubernetes
Dr.kangder5 小时前
嵌入式处理器仿真技术——Hypervisor 原理与实践
服务器·嵌入式硬件·架构·嵌入式
_艾伦 耶格尔.5 小时前
基础I/O
linux
星蓝_starblue7 小时前
零服务器、零数据库!开源growth-board,利用GitHub自动管理刷题/学习/求职全流程
服务器·数据库·程序人生·系统架构·node.js·github·改行学it
fb_123458 小时前
Linux磁盘分区从入门到实操:MBR_GPT全解析+分区工具实战指南
java·linux·gpt