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

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信号方式通知

当需要在定时器到期时触发一个信号,并且希望在信号处理器中执行特定的操作时使用。这是最常见的用法之一,适用于需要实时响应的应用程序

  1. 创建信号捕捉器sigaction
  2. 创建定时器timer_create
  3. 启动定时器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启动线程方式通知

当需要在一个新的线程中执行某个函数来处理定时器事件时使用。这种方式提供了更多的灵活性,因为你可以执行任意复杂的任务,而不受信号处理函数的限制。

  1. 创建线程函数
  2. 创建定时器timer_create
  3. 启动定时器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…...

重拾设计模式--观察者模式

文章目录 观察者模式&#xff08;Observer Pattern&#xff09;概述观察者模式UML图作用&#xff1a;实现对象间的解耦支持一对多的依赖关系易于维护和扩展 观察者模式的结构抽象主题&#xff08;Subject&#xff09;&#xff1a;具体主题&#xff08;Concrete Subject&#xf…...

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 - 石头剪刀布

一、游戏基础&#xff1a;拳头、掌心、分指 首先&#xff0c;石头剪刀布&#xff08;又名“Roshambo”&#xff09;看似简单&#xff0c;实际上可是个“深藏玄机”的零和博弈&#xff08;听起来很高深&#xff0c;其实就是输赢相抵消的意思&#xff09;。游戏中有三种手势&…...

3-Gin 渲染 --[Gin 框架入门精讲与实战案例]

在 Gin 框架中&#xff0c;渲染指的是将数据传递给模板&#xff0c;并生成 HTML 或其他格式的响应内容。Gin 支持多种类型的渲染&#xff0c;包括 String HTML、JSON、XML 等。 String 渲染 在 Gin 框架中&#xff0c;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 字矩阵&#xff08; 为奇数&#xff09;&#xff0c;这个矩阵的两条对角线都是半角加号 &#xff0c;其余都是半角减号 - 。例如&#xff0c;一个 5 5 5 \times 5 5…...

@PostConstruct注解解释!!!!

PostConstruct 注解修饰的方法是在 Bean 完成初始化后自动调用的。它是 Java EE 和 Spring 中的一种机制&#xff0c;用于在 Bean 被创建并依赖注入完成后&#xff0c;执行一些初始化的操作。 具体触发时机&#xff1a; 依赖注入完成后&#xff1a;首先&#xff0c;Spring 容器…...

laya游戏引擎中打包之后图片模糊

如下图正常运行没问题&#xff0c;打包之后却模糊 纹理类型中的默认类型都是精灵纹理&#xff0c;改为默认值即可。注意&#xff1a;要点击“应用”才可有效。精灵纹理类型会对图片进行渲染处理&#xff0c;而默认值 平面类型不会处理图片。...

【数据结构练习题】链表与LinkedList

顺序表与链表LinkedList 选择题链表面试题1. 删除链表中等于给定值 val 的所有节点。2. 反转一个单链表。3. 给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。4. 输入一个链表&#xff0c;输出该链…...

[项目代码] YOLOv8 遥感航拍飞机和船舶识别 [目标检测]

项目代码下载链接 &#xff1c;项目代码&#xff1e;YOLO 遥感航拍飞机和船舶识别&#xff1c;目标检测&#xff1e;https://download.csdn.net/download/qq_53332949/90163939YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为…...

移动魔百盒中的 OpenWrt作为旁路由 安装Tailscale并配置子网路由实现在外面通过家里的局域网ip访问内网设备

移动魔百盒中的 OpenWrt作为旁路由 安装Tailscale并配置子网路由实现在外面通过家里的局域网ip访问内网设备 一、前提条件 确保路由器硬件支持&#xff1a; OpenWrt 路由器需要足够的存储空间和 CPU 性能来运行 Tailscale。确保设备架构支持 Tailscale 二进制文件&#xff0c;例…...

JVM对象分配内存如何保证线程安全?

大家好&#xff0c;我是锋哥。今天分享关于【JVM对象分配内存如何保证线程安全&#xff1f;】面试题。希望对大家有帮助&#xff1b; JVM对象分配内存如何保证线程安全&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在JVM中&#xff0c;对象的内存分配…...

ArcGIS计算土地转移矩阵

在计算土地转移矩阵时&#xff0c;最常使用的方法就是在ArcGIS中将土地利用栅格数据转为矢量&#xff0c;然后采用叠加分析计算&#xff0c;但这种方法计算效率低。还有一种方法是采用ArcGIS中的栅格计算器&#xff0c;将一个年份的地类编号乘以个100或是1000再加上另一个年份的…...

数据库 MYSQL的概念

数据库的概念 数据库是按照数据结 构来组织、存储和管理数据的系统&#xff0c;它允许用户高效地存储、检索、更新和管理数据 database&#xff1a;用来组织&#xff0c;存储&#xff0c;管理数据的仓库 数据库的管理系统&#xff1a;DBMS&#xff0c;实现对数据的有效储值&am…...

Node.js后端程序打包问题汇总(webpack、rsbuild、fastify、knex、objection、sqlite3、svg-captcha)

背景说明 场景 使用 node.js 进行后端开发&#xff0c;部署时通常需要打包为单文件&#xff0c;然后放到服务器运行。 这里记录我在打包过程中&#xff0c;碰到的各类问题及解决方案&#xff0c;希望能够帮助到更多道友&#x1f604; 提示 此文持续更新&#xff0c;可以收藏⭐…...

部署 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&#xff1a;xiaomi R4C官方固件&#xff1a;openwrt 23.05.5 &#xff08;下图标红处&#xff09;官方教程 下载 OpenWRTInvasionpython remote_command_execution_vulnerability.py …...

leetcode-128.最长连续序列-day14

为什么我感觉上述代码时间复杂度接近O(2n), 虽然有while循环&#xff0c;但是前面有个if判断&#xff0c;能进入while循环的也不多&#xff0c;while循环就相当于两个for循环&#xff0c;但不是嵌套类型的&#xff1a; 变量作用域问题&#xff1a;...

梳理你的思路(从OOP到架构设计)_简介设计模式

目录 1、 模式(Pattern) 是较大的结构​编辑 2、 结构形式愈大 通用性愈小​编辑 3、 从EIT造形 组合出设计模式 1、 模式(Pattern) 是较大的结构 组合与创新 達芬奇說&#xff1a;簡單是複雜的終極形式 (Simplicity is the ultimate form of sophistication) —Leonardo d…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...