linux定时器操作
目录
- 1 简单示例
- 2 timer_create方式
- 2.1 SIGEV_SIGNAL信号方式通知
- 2.2 SIGEV_THREAD启动线程方式通知
- 2.3 参数
1 简单示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>void setup_timer(int seconds) {struct itimerval new_value, old_value;// 设置定时器初始值new_value.it_value.tv_sec = seconds;new_value.it_value.tv_usec = 0;// 设置定时器触发周期,0表示不重复new_value.it_interval.tv_sec = 0;new_value.it_interval.tv_usec = 0;// 设置定时器类型为ITIMER_REALsetitimer(ITIMER_REAL, &new_value, &old_value);
}void signal_handler(int sig) {if (sig == SIGALRM) {printf("Timer expired\n");}
}int main() {// 设置信号处理函数signal(SIGALRM, signal_handler);// 设置定时器,每1秒触发一次setup_timer(1);// 执行其他任务while(1) {sleep(1);}return 0;
}
2 timer_create方式
2.1 SIGEV_SIGNAL信号方式通知
当需要在定时器到期时触发一个信号,并且希望在信号处理器中执行特定的操作时使用。这是最常见的用法之一,适用于需要实时响应的应用程序
- 创建信号捕捉器
sigaction - 创建定时器
timer_create - 启动定时器
timer_settimer
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>// 信号处理函数
void signal_handler(int signum, siginfo_t *info, void *context) {if (signum == SIGUSR1) {//使用设置的info->si_value.sival_ptr来判断定时器编号printf("Timer 1 expired, data: %p\n", info->si_value.sival_ptr);}
}int main() {struct sigevent sev1, sev2;timer_t timerid1, timerid2;// TODO 设置信号处理器struct sigaction sa;sa.sa_flags = SA_SIGINFO; // 使用 sa_sigaction 而不是 sa_handlersa.sa_sigaction = signal_handler;sigemptyset(&sa.sa_mask);if (sigaction(SIGUSR1, &sa, NULL) == -1 || sigaction(SIGUSR2, &sa, NULL) == -1) {perror("sigaction");exit(EXIT_FAILURE);}// TODO 配置第一个定时器sev1.sigev_notify = SIGEV_SIGNAL;sev1.sigev_signo = SIGUSR1;sev1.sigev_value.sival_ptr = (void*) "Timer 1";if (timer_create(CLOCK_REALTIME, &sev1, &timerid1) == -1) {perror("timer_create for timer 1");exit(EXIT_FAILURE);}// TODO 配置第二个定时器sev2.sigev_notify = SIGEV_SIGNAL;sev2.sigev_signo = SIGUSR1;sev2.sigev_value.sival_ptr = (void*) "Timer 2";if (timer_create(CLOCK_REALTIME, &sev2, &timerid2) == -1) {perror("timer_create for timer 2");exit(EXIT_FAILURE);}// 设置定时器1到期时间struct itimerspec its1;its1.it_value.tv_sec = 5;its1.it_value.tv_nsec = 0;its1.it_interval.tv_sec = 0;its1.it_interval.tv_nsec = 0;if (timer_settime(timerid1, 0, &its1, NULL) == -1) {perror("timer_settime for timer 1");exit(EXIT_FAILURE);}// 设置定时器2到期时间struct itimerspec its2;its2.it_value.tv_sec = 10;its2.it_value.tv_nsec = 0;its2.it_interval.tv_sec = 0;its2.it_interval.tv_nsec = 0;if (timer_settime(timerid2, 0, &its2, NULL) == -1) {perror("timer_settime for timer 2");exit(EXIT_FAILURE);}// 保持程序运行while (1) {pause();}return 0;
}
2.2 SIGEV_THREAD启动线程方式通知
当需要在一个新的线程中执行某个函数来处理定时器事件时使用。这种方式提供了更多的灵活性,因为你可以执行任意复杂的任务,而不受信号处理函数的限制。
- 创建线程函数
- 创建定时器
timer_create - 启动定时器
timer_settimer
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>// 线程函数
void* timer_thread_function(union sigval sv) {printf("Timer thread started, data: %p\n", sv.sival_ptr);// 在这里执行你的定时器任务sleep(2);return NULL;
}int main() {struct sigevent sev1, sev2;timer_t timerid1, timerid2;// 配置第一个定时器sev1.sigev_notify = SIGEV_THREAD;sev1.sigev_notify_function = timer_thread_function;sev1.sigev_value.sival_ptr = (void*) "Timer 1";if (timer_create(CLOCK_REALTIME, &sev1, &timerid1) == -1) {perror("timer_create for timer 1");exit(EXIT_FAILURE);}// 配置第二个定时器sev2.sigev_notify = SIGEV_THREAD;sev2.sigev_notify_function = timer_thread_function;sev2.sigev_value.sival_ptr = (void*) "Timer 2";if (timer_create(CLOCK_REALTIME, &sev2, &timerid2) == -1) {perror("timer_create for timer 2");exit(EXIT_FAILURE);}// 设置定时器到期时间struct itimerspec its1, its2;// 定时器1:5秒后到期its1.it_value.tv_sec = 5;its1.it_value.tv_nsec = 0;its1.it_interval.tv_sec = 0;its1.it_interval.tv_nsec = 0;if (timer_settime(timerid1, 0, &its1, NULL) == -1) {perror("timer_settime for timer 1");exit(EXIT_FAILURE);}// 定时器2:10秒后到期its2.it_value.tv_sec = 10;its2.it_value.tv_nsec = 0;its2.it_interval.tv_sec = 0;its2.it_interval.tv_nsec = 0;if (timer_settime(timerid2, 0, &its2, NULL) == -1) {perror("timer_settime for timer 2");exit(EXIT_FAILURE);}// 保持程序运行while (1) {pause();}return 0;
}
注意事项
- 线程资源管理: 每次定时器到期都会创建一个新的线程。如果定时器频繁到期,可能会导致大量的线程被创建,从而消耗大量系统资源。在这种情况下,可以考虑使用线程池或其他资源管理机制来优化线程的创建和销毁
- 线程安全: 如果线程函数需要访问共享资源,确保这些操作是线程安全的,可能需要使用互斥锁或其他同步机制。
2.3 参数
sigevent 结构体用于指定当定时器到期或其他事件发生时,系统应该如何通知应用程序。sigevent.sigev_notify 成员可以设置为不同的值,以选择不同的通知方式。常见的几种方式包括:
SIGEV_NONE
说明:不进行任何通知。
使用场景:当你不需要在定时器到期时收到任何通知时使用。例如,你可能只是想让定时器运行并记 录某些内部状态,而不需要立即处理。
SIGEV_SIGNAL:
说明:通过发送信号来通知。
使用场景:当需要在定时器到期时触发一个信号,并且希望在信号处理器中执行特定的操作时使用。这是最常见的用法之一,适用于需要实时响应的应用程序。
配置:需要设置 sigev_signo 为要发送的信号编号,还可以设置 sigev_value 传递额外的数据给信号处理器。
SIGEV_THREAD:
说明:通过创建一个新的线程来通知。
使用场景:当需要在一个新的线程中执行某个函数来处理定时器事件时使用。这种方式提供了更多的灵活性,因为你可以执行任意复杂的任务,而不受信号处理函数的限制。
配置:需要设置 sigev_notify_function 为要调用的函数指针,sigev_notify_attributes 可以设置线程属性(可选),sigev_value 可以传递参数给该函数。
SIGEV_THREAD_ID (POSIX.1-2008 及更高版本):
说明:通过向指定的线程发送信号来通知。
使用场景:当需要将信号发送到特定的线程而不是整个进程时使用。这种方式允许更细粒度的控制,特别是在多线程环境中。
配置:需要设置 sigev_notify_thread_id 为目标线程的线程ID,sigev_signo 为要发送的信号编号,sigev_value 可以传递额外的数据。
相关文章:
linux定时器操作
目录 1 简单示例2 timer_create方式2.1 SIGEV_SIGNAL信号方式通知2.2 SIGEV_THREAD启动线程方式通知2.3 参数 1 简单示例 #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <signal.h> #include <unistd.h>void setup_t…...
重拾设计模式--观察者模式
文章目录 观察者模式(Observer Pattern)概述观察者模式UML图作用:实现对象间的解耦支持一对多的依赖关系易于维护和扩展 观察者模式的结构抽象主题(Subject):具体主题(Concrete Subject…...
Vue.js前端框架教程7:Vue计算属性和moment.js
文章目录 计算属性(Computed Properties)基本用法缓存机制计算属性 vs 方法使用场景计算属性的 setter 和 getter结论Moment.js 进行时间处理1. 安装 Moment.js2. 在 Vue 组件中引入 Moment.js3. 在全局使用 Moment.js4. 使用 Vue 插件的方式引入 Moment.js5. 常用日期格式化…...
【游戏设计原理】22 - 石头剪刀布
一、游戏基础:拳头、掌心、分指 首先,石头剪刀布(又名“Roshambo”)看似简单,实际上可是个“深藏玄机”的零和博弈(听起来很高深,其实就是输赢相抵消的意思)。游戏中有三种手势&…...
3-Gin 渲染 --[Gin 框架入门精讲与实战案例]
在 Gin 框架中,渲染指的是将数据传递给模板,并生成 HTML 或其他格式的响应内容。Gin 支持多种类型的渲染,包括 String HTML、JSON、XML 等。 String 渲染 在 Gin 框架中,String 渲染方法允许你直接返回一个字符串作为 HTTP 响应…...
python小课堂(一)
基础语法 1 常量和表达式2 变量和类型2.1 变量是什么2.2 变量语法 3 变量的类型3.1 动态类型特性 4 注释4.1注释是什么 5 输入输出5.1 print的介绍5.2 input 6 运算符6.1 算术运算符在这里插入图片描述6.2 关系运算符6.3 逻辑运算符6.4赋值运算符 1 常量和表达式 在print()中可…...
GESP202309 二级【小杨的 X 字矩阵】题解(AC)
》》》点我查看「视频」详解》》》 [GESP202309 二级] 小杨的 X 字矩阵 题目描述 小杨想要构造一个 的 X 字矩阵( 为奇数),这个矩阵的两条对角线都是半角加号 ,其余都是半角减号 - 。例如,一个 5 5 5 \times 5 5…...
@PostConstruct注解解释!!!!
PostConstruct 注解修饰的方法是在 Bean 完成初始化后自动调用的。它是 Java EE 和 Spring 中的一种机制,用于在 Bean 被创建并依赖注入完成后,执行一些初始化的操作。 具体触发时机: 依赖注入完成后:首先,Spring 容器…...
laya游戏引擎中打包之后图片模糊
如下图正常运行没问题,打包之后却模糊 纹理类型中的默认类型都是精灵纹理,改为默认值即可。注意:要点击“应用”才可有效。精灵纹理类型会对图片进行渲染处理,而默认值 平面类型不会处理图片。...
【数据结构练习题】链表与LinkedList
顺序表与链表LinkedList 选择题链表面试题1. 删除链表中等于给定值 val 的所有节点。2. 反转一个单链表。3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。4. 输入一个链表,输出该链…...
[项目代码] YOLOv8 遥感航拍飞机和船舶识别 [目标检测]
项目代码下载链接 <项目代码>YOLO 遥感航拍飞机和船舶识别<目标检测>https://download.csdn.net/download/qq_53332949/90163939YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为…...
移动魔百盒中的 OpenWrt作为旁路由 安装Tailscale并配置子网路由实现在外面通过家里的局域网ip访问内网设备
移动魔百盒中的 OpenWrt作为旁路由 安装Tailscale并配置子网路由实现在外面通过家里的局域网ip访问内网设备 一、前提条件 确保路由器硬件支持: OpenWrt 路由器需要足够的存储空间和 CPU 性能来运行 Tailscale。确保设备架构支持 Tailscale 二进制文件,例…...
JVM对象分配内存如何保证线程安全?
大家好,我是锋哥。今天分享关于【JVM对象分配内存如何保证线程安全?】面试题。希望对大家有帮助; JVM对象分配内存如何保证线程安全? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在JVM中,对象的内存分配…...
ArcGIS计算土地转移矩阵
在计算土地转移矩阵时,最常使用的方法就是在ArcGIS中将土地利用栅格数据转为矢量,然后采用叠加分析计算,但这种方法计算效率低。还有一种方法是采用ArcGIS中的栅格计算器,将一个年份的地类编号乘以个100或是1000再加上另一个年份的…...
数据库 MYSQL的概念
数据库的概念 数据库是按照数据结 构来组织、存储和管理数据的系统,它允许用户高效地存储、检索、更新和管理数据 database:用来组织,存储,管理数据的仓库 数据库的管理系统:DBMS,实现对数据的有效储值&am…...
Node.js后端程序打包问题汇总(webpack、rsbuild、fastify、knex、objection、sqlite3、svg-captcha)
背景说明 场景 使用 node.js 进行后端开发,部署时通常需要打包为单文件,然后放到服务器运行。 这里记录我在打包过程中,碰到的各类问题及解决方案,希望能够帮助到更多道友😄 提示 此文持续更新,可以收藏⭐…...
部署 Apache Samza 和 Apache Kafka
部署 Apache Samza 和 Apache Kafka 的流处理系统可以分为以下几个步骤,涵盖环境准备、部署细节和生产环境的优化。 1. 环境准备 硬件要求 Kafka Broker:至少 3 台服务器,建议每台服务器配备 4 核 CPU、16GB 内存和高速磁盘。Samza 部署节点:根据任务规模,至少准备 2 台…...
xiaomiR4c openwrt
文章目录 openwrt 安装openwrt 配置开启WiFi 救砖minieap编译参数帮助 openwrt 安装 Router:xiaomi R4C官方固件:openwrt 23.05.5 (下图标红处)官方教程 下载 OpenWRTInvasionpython remote_command_execution_vulnerability.py …...
leetcode-128.最长连续序列-day14
为什么我感觉上述代码时间复杂度接近O(2n), 虽然有while循环,但是前面有个if判断,能进入while循环的也不多,while循环就相当于两个for循环,但不是嵌套类型的: 变量作用域问题:...
梳理你的思路(从OOP到架构设计)_简介设计模式
目录 1、 模式(Pattern) 是较大的结构编辑 2、 结构形式愈大 通用性愈小编辑 3、 从EIT造形 组合出设计模式 1、 模式(Pattern) 是较大的结构 组合与创新 達芬奇說:簡單是複雜的終極形式 (Simplicity is the ultimate form of sophistication) —Leonardo d…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...
