Linux提供的定时器

定时器在许多场景中非常有用,尤其是在需要精确定时或定时执行某些任务的情况下。而Linux专门为定时器提供了一套定时器接口。

timerfd_creat

timerfd_create是 Linux 中用于创建定时器文件描述符的函数。这个功能主要是用来在指定的时间后或定时间隔内触发事件,适用于需要精确定时的应用。

#include <sys/timerfd.h>
int timerfd_create(int clockid, int flags);

clockid:指定计时器所使用的时钟,可以是 CLOCK_REALTIMECLOCK_MONOTONIC

  • CLOCK_REALTIME:系统实时时钟,从1970-01-01 00:00:00 UTC计时。
  • CLOCK_MONOTONIC:系统启动后经过的时间,不受系统时间变化的影响。

flags:可以是 0 或 TFD_NONBLOCK、TFD_CLOEXEC 的组合。

  • TFD_NONBLOCK:使文件描述符在非阻塞模式下工作。
  • TFD_CLOEXEC:在执行 exec() 系统调用时自动关闭文件描述符。

timerfd_create 的返回值是一个文件描述符,用于标识创建的定时器。如果创建成功,它返回一个非负的文件描述符;如果失败,它返回 -1,并设置 errno 来指示错误原因。

itimerspec

itimerspec 是一个结构体,用于指定定时器的初始启动时间和间隔时间。

该结构体定义在头文件 <time.h> 中,结构如下:

struct itimerspec {struct timespec it_interval; /* Interval for periodic timer */struct timespec it_value;    /* Initial expiration */
};
  • it_interval:指定定时器的周期。如果定时器是单次触发,这个值应为 0。
  • it_value:指定定时器的初始启动时间。

其中

  1. 初始启动时间指的是定时器从设定(调用 timerfd_settime 函数)后开始计时,到第一次触发之间的时间间隔。
  2. 指定周期指的是定时器在初始启动时间后,以固定的时间间隔重复触发事件的机制。

timespec 结构体

itimerspec 中包含的两个字段 it_intervalit_value 均是 timespec 结构体类型。timespec 结构体定义如下:

struct timespec {time_t tv_sec;  /* seconds */long   tv_nsec; /* nanoseconds */
};
  • tv_sec:以秒为单位的时间。
  • tv_nsec:以纳秒为单位的时间。

timerfd_settime

timerfd_settime 是用于设置和启动定时器的函数,它与 timerfd_create 一起使用来控制定时器的行为。timerfd_settime 函数允许你指定定时器的初始启动时间和周期时间。

int timerfd_settime(int fd, int flags,const struct itimerspec *new_value,struct itimerspec *old_value);
参数解释

fd:由 timerfd_create 返回的定时器文件描述符。

flags:指定定时器的行为,可以是以下值之一:

  • 0:相对时间,从当前时间开始计时。
  • TFD_TIMER_ABSTIME:绝对时间,从指定的时间点(即从 UNIX 纪元(1970年1月1日)以来的秒数和纳秒数)开始计时。

new_value:指向一个 itimerspec 结构体,定义定时器的初始启动时间和周期时间。

old_value:如果不为 NULL,该结构体将保存上一次的定时器设定值。

定时器设置中的时间点

定时器的设置可以涉及两种主要的时间表示方式:

  1. 相对时间:定时器从设置的那一刻起开始计时。
  2. 绝对时间:定时器从指定的系统时间点开始计时。
使用绝对时间点

当使用 TFD_TIMER_ABSTIME 标志时,it_value 代表的是一个绝对时间点,即从 UNIX 纪元(1970年1月1日)以来的秒数和纳秒数。因此,定时器将从当前时间加上 it_value 指定的时间点开始计时。

timerfd_gettime

timerfd_gettime 是一个系统调用函数,用于获取定时器的当前状态,包括定时器的剩余时间和定时器的周期时间。这个函数对于检查定时器的状态或获取定时器当前剩余的时间非常有用。

int timerfd_gettime(int fd, struct itimerspec *curr_value);
参数说明

fd:定时器文件描述符,是通过 timerfd_create 创建的。

curr_value(输出型参数):指向 itimerspec 结构体的指针,用于接收定时器的当前状态。itimerspec 结构体包括:

  • it_value:定时器的剩余时间(即下次到期时间的时间点)。
  • it_interval:定时器的周期时间。
返回值
  • 成功时返回 0
  • 失败时返回 -1 并设置 errno 以指示错误类型。

clock_gettime

int clock_gettime(clockid_t clk_id, struct timespec *tp);
参数解释
  • clk_id:时钟标识符,指定要获取时间的时钟。常见的时钟类型包括:
    • CLOCK_REALTIME:系统实时时钟,表示当前的系统时间,从 UNIX 纪元(1970年1月1日)以来的秒数。
    • CLOCK_MONOTONIC:单调时钟,表示系统启动以来的时间,不受系统时间调整的影响。
    • CLOCK_PROCESS_CPUTIME_ID:当前进程的 CPU 时间。
    • CLOCK_THREAD_CPUTIME_ID:当前线程的 CPU 时间。
  • tp:指向 timespec 结构体的指针,用于接收获取的时间信息。
返回值
  • 成功时返回 0
  • 失败时返回 -1 并设置 errno 以指示错误类型。

例子

#include <iostream>
#include <sys/timerfd.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <ctime>int main() {// 创建 timerfdint timerfd = timerfd_create(CLOCK_REALTIME, 0);if (timerfd == -1) {std::cerr << "Failed to create timerfd: " << strerror(errno) << std::endl;return 1;}// 设置定时器struct itimerspec new_value;new_value.it_value.tv_sec = 5;  // 初始启动时间为5秒后new_value.it_value.tv_nsec = 0;new_value.it_interval.tv_sec = 1;  // 周期为1秒new_value.it_interval.tv_nsec = 0;if (timerfd_settime(timerfd, 0, &new_value, NULL) == -1) {std::cerr << "Failed to set timer: " << strerror(errno) << std::endl;close(timerfd);return 1;}// 获取定时器状态struct itimerspec curr_value;if (timerfd_gettime(timerfd, &curr_value) == -1) {std::cerr << "Failed to get timer time: " << strerror(errno) << std::endl;close(timerfd);return 1;}// 输出当前状态std::cout << "Current timer status:" << std::endl;std::cout << "Time until next expiration (seconds): " << curr_value.it_value.tv_sec << std::endl;std::cout << "Time until next expiration (
解释
  1. 创建定时器:通过 timerfd_create 创建一个定时器文件描述符。

  2. 设置定时器:使用 timerfd_settime 配置定时器的初始启动时间和周期时间。

  3. 获取定时器状态

    调用 timerfd_gettime 获取定时器的当前状态,将结果存储在 curr_value 中。curr_value 是一个 itimerspec 结构体,它会被填充为定时器的剩余时间和周期时间。

  4. 输出状态信息:打印定时器的当前初始到期时间和周期时间。

  5. 关闭定时器:在程序结束时关闭定时器文件描述符。

定时器的使用场景

定时器在许多应用场景中都非常有用,特别是在需要精确时间控制和事件调度的情况下。以下是一些常见的使用场景:

  1. 周期性任务调度
    • 例如,每隔一段时间执行一次某个任务,如数据采集、日志记录、性能监控等。
  2. 超时控制
    • 在网络编程中,可以设置定时器来检测连接超时、数据传输超时等。
    • 在用户输入处理中,可以设置定时器来检测用户的长时间不操作等情况。
  3. 定时事件触发
    • 用于在特定时间点触发某些事件,如定时提醒、定时任务执行等。
  4. 性能测量
    • 通过测量代码执行时间来分析性能瓶颈,优化程序效率。

使用定时器的建议

  1. 选择合适的定时器类型
    • 根据具体需求选择适当的定时器类型,如 CLOCK_REALTIME 用于实际时间触发,CLOCK_MONOTONIC 用于系统启动后的持续时间触发,不受系统时间修改的影响。
  2. 设置合理的时间间隔和初始启动时间
    • 根据任务的重要性和执行频率设置合适的时间间隔,避免不必要的频繁触发导致系统资源浪费。
  3. 处理定时器触发事件
    • 在定时器触发事件时,确保及时处理,避免积压事件导致定时器触发延迟。
    • 使用非阻塞 I/O 或者多线程来处理定时器触发事件,确保系统的其他部分不受影响。
  4. 检查和调整定时器状态
    • 使用 timerfd_gettime 检查定时器的当前状态,确保定时器运行如预期。
    • 在必要时动态调整定时器的时间设置,以适应变化的需求。
  5. 资源管理
    • 在程序结束或不再需要定时器时,确保关闭定时器文件描述符,释放系统资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/48207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TS的访问修饰符有哪些

如果你和我一样是从强类型语言(如C、C#、Java)转过来的&#xff0c;相信你会一眼就知道是什么 public&#xff08;默认&#xff09; - 全部可访问 protected - 自己和派生类可访问 private - 只有自己可访问 废话不多说&#xff0c;上代码&#xff1a; class Person {publ…

Docker容器逃逸漏洞-CVE-2024-21626

Snyk 在 Docker 引擎以及其他容器化技术(例如 Kubernetes)使用的 runc <=1.1.11 的所有版本中发现了一个漏洞。利用此问题可能会导致容器逃逸到底层主机操作系统,无论是通过执行恶意映像还是使用恶意 Dockerfile 或上游映像构建映像(即使用时FROM) CVE-2024-21626原理…

生成式人工智能之路,从马尔可夫链到生成对抗网络

人工智能&#xff08;Artificial intelligence&#xff0c;AI&#xff09;技术在过去几年中取得了显著进展&#xff0c;其中生成式AI&#xff08;Generative AI&#xff09;因其强大的内容生成能力而备受关注。生成式AI可以创建新的文本、图像、音频、视频、代码以及其他形式的…

SSRF学习笔记

1.NAT学习 Nat&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;是 一种网络通信技术主要用于将私有网络中的内部IP地址转换成公共网络中的公共IP地址&#xff0c;以实现局域网内部设备访问互联网的功能。具体来说&#xff0c;Nat有以下几个主要…

Python应用—实现和改良word邮件合并功能

1.实现目的 邮件合并也有其缺陷,那就是每次合并数据都需操作插入合并域,如果经常需要根据数据生成固定模板word文件,那么就显得很麻烦 显然利用程序固定数据替换模式就极为方便,需要生成文件时可以一键操作 2.代码实现 import os.path import xlrd from mailmerge impo…

Python 提示框

安装&#xff1a; pip install tk0.1.0第三方库地址&#xff1a; https://pypi.org/project/tk/ # 方法一 # -*- coding: UTF-8 -*-from tkinter import messagebox from tkinter import Tkroot Tk() root.withdraw() messagebox.showinfo("提示框", "这是一个…

Matlab画不同指标的对比图

目录 一、指标名字可修改 二、模型名字可修改 三、输入数据可修改 软件用的是Matlab R2024a。 clear,clc,close all figure1figure(1); % set(figure1,Position,[300,100,800,600],Color,[1 1 1]) axes1 axes(Parent,figure1);%% Initialize data points 一、指标名字可修…

MongoDB 学习笔记

一、简介 1、MongoDB 是什么 MongoDB 是一个基于分布式文件存储的数据库&#xff0c;官方地址 https://www.mongodb.com/ 2、数据看是什么 数据库&#xff08;DataBase&#xff09;是按照数据结构来组织、存储和管理数据的应用程序。 3、数据库的作用 主要作用是 管理数据…

mybatis中的缓存(一级缓存、二级缓存)

文章目录 前言一、MyBatis 缓存概述二、一级缓存1_初识一级缓存2_一级缓存命中原则1_StatementId相同2_查询参数相同3_分页参数相同4_sql 语句5_环境 3_一级缓存的生命周期1_缓存的产生2_缓存的销毁3_网传的一些谣言 4_一级缓存核心源码5_总结 三、二级缓存1_开启二级缓存2_二级…

利用深度学习模型BiLSTM进行数据预测和分析

1. 导入必要的库和模块&#xff1a; python import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score import matplot…

如何选择适合的数据仓库ETL工具

在数据仓库的建设中&#xff0c;选择合适的ETL&#xff08;数据提取、转换和加载&#xff09;工具至关重要。本文将以两款常见的ETL工具——Informatica和Kettle为例&#xff0c;分享如何选择适合的ETL工具来支持数据仓库的构建和管理。通过对比它们的特点和应用场景&#xff0…

Pytorch 9

softmax多分类问题 import torch from torchvision import datasets from torch.utils.data import DataLoader import torch.nn.functional as F# 激活函数 import torch.optim as optim # optim.SGD (随机梯度下降)&#xff1a;最基础的优化算法&#xff0c;通过沿着梯度的反…

初等数论精解【5】

文章目录 不定方程基础理论不定方程例子 1: 线性不定方程例子 2: 整数解的不定方程例子 3: 含有多个未知数的不定方程总结 参考文献 不定方程 基础 一元不定方程 1. a 1 x a 0 0 x − a 0 a 1 &#xff0c;但是不能保证有整数解 2. a n x n a n − 1 x n − 1 . . . a…

Springboot 启动时Bean的创建与注入(二)-面试热点-springboot源码解读-xunznux

Springboot 启动时Bean的创建与注入&#xff0c;以及对应的源码解读 文章目录 Springboot 启动时Bean的创建与注入&#xff0c;以及对应的源码解读11、getBean:200, AbstractBeanFactory (org.springframework.beans.factory.support)12、doGetBean:335, AbstractBeanFactory (…

Vue系列面试题

大家好&#xff0c;我是有用就扩散&#xff0c;有用就点赞。 1.Vue中组件间有哪些通信方式&#xff1f; 父子组件通信&#xff1a; &#xff08;1&#xff09;props | $emit &#xff08;接收父组件数据 | 传数据给父组件&#xff09; &#xff08;2&#xff09;ref | $refs&a…

基于Hutool实现自定义模板引擎,实现json个性化模板引擎转换

文章目录 前言编写引擎类&#xff1a;JsonTemplateEngine编写模板类&#xff1a;CustomTemplate编写测试代码测试json文件测试类 前言 由于百度搜索json模板引擎&#xff0c;推荐的都是一些freemarker之类的&#xff0c;需要引入其他的依赖&#xff0c;而且在编写json模板的时…

学习在测试时学习(Learning at Test Time)_ 具有表达性隐藏状态的循环神经网络(RNNs)

摘要 https://arxiv.org/pdf/2407.04620 自注意力机制在长文本语境中表现良好&#xff0c;但其复杂度为二次方。现有的循环神经网络&#xff08;RNN&#xff09;层具有线性复杂度&#xff0c;但其在长文本语境中的性能受到隐藏状态表达能力的限制。我们提出了一种新的序列建模…

LabVIEW多线圈电磁式振动发电机测试

开发了一种基于LabVIEW设计的多线圈电磁式振动发电机测试系统。系统通过高效的数据采集、波峰检测及相位差计算&#xff0c;优化了传统振动发电机的测试流程&#xff0c;提升了电压波形分析的精度和效率&#xff0c;具有较好的应用前景和推广价值。 项目背景 随着可再生能源技…

跨越数据边界:域适应提升目标检测的泛化之舞

跨越数据边界&#xff1a;域适应提升目标检测的泛化之舞 目标检测模型在实际应用中常常面临泛化能力不足的问题&#xff0c;尤其是在数据源和部署环境不一致的情况下。域适应&#xff08;Domain Adaptation&#xff09;技术通过减少源域&#xff08;有标签数据&#xff09;和目…

遇到not allow unquoted fieldName怎么办

前言 Exception in thread "main" com.alibaba.fastjson2.JSONException: not allow unquoted fieldName, offset 2, character , line 1, column 3, fastjson-version 2.0.25 { "data":null, "code":200, "msg":"成功"…