当前位置: 首页 > article >正文

Linux提供给我们的定时器

timerfd_create 和 timerfd_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_BOOTTIMECLOCK_MONOTONIC 类似,但包括系统挂起时间
flags控制定时器的行为
TFD_NONBLOCK设置文件描述符为非阻塞模式
TFD_CLOEXEC设置文件描述符为 close-on-exec(执行 exec 时自动关闭)

返回值

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

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

2. timerfd_settime

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

函数原型:

#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 结构体,用于设置定时器的初始值和间隔值。

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。

示例:

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

适用场景

  • 周期性任务调度。

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

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

 


http://www.kler.cn/a/538456.html

相关文章:

  • AD域控粗略了解
  • TCP三次握手全方面详解
  • 借助AI,轻松读好书
  • 【AIGC】语言模型的发展历程:从统计方法到大规模预训练模型的演化
  • Spring Boot统一异常拦截实践指南
  • OpenCV:视频背景减除
  • 【k8s集群应用】kubenetes-YAML
  • QT实现多线程的方法
  • 谷歌浏览器多开指南:如何完成独立IP隔离?
  • 在线免费 HTML 预览导出为图片,并且支持水平切割
  • 基于Flask的汽车质量投诉可视化分析系统的设计与实现
  • 手写一个C++ Android Binder服务及源码分析
  • Java模块化 - 基本介绍
  • 0 CAD开源内核 Truck
  • 【数据结构】(7) 栈和队列
  • 如何在RTACAR中配置IP多播(IP Multicast)
  • 一款由 .NET 官方团队开源的电子商务系统 - eShop
  • python基础语法--笔记1
  • DeepSeek与ChatGPT对比:技术、应用与未来趋势
  • Tekton 可以代替 Jenkins不
  • DNS攻击方式有哪些,应该采取哪些应对措施?
  • c++加载TensorRT调用深度学习模型方法
  • 跟着李沐老师学习深度学习(五)
  • ESP32的IDF实现C语言和C++语言的混合编译
  • P1049 装箱问题(dp)
  • C++ 字符串编码转换