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 可以传递额外的数据。

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

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

相关文章

设计模式之【观察者模式】

观察者模式&#xff1a; 应用于发布-订阅消息模型中&#xff0c;订阅者订阅一个主题后&#xff0c;当有新消息到达时&#xff0c;所有订阅者都会收到通知。 主要关注的是对象之间的通信。是一种对象之间的一对多关系&#xff0c;多个对象依赖于一个对象&#xff0c;当被依赖的…

页面无滚动条,里面div各自有滚动条

一、双滚动条左右布局 实现效果 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Doc…

(Z Shell)zsh: no matches found: ? 使用单引号包裹

文章目录 dgqdgqdeMac-mini ProductAuthentication % git commit -m "open-type"{{isCodeValid ? getPhoneNumber : none}}"" zsh: no matches found: ?git commit -m open-type"{{isCodeValid ? getPhoneNumber : none}}"你遇到的 zsh: no m…

鸿蒙元服务从0到上架【第二篇】

第一招&#xff1a;在AppGallery后台下载对应的证书等文件 AppGallery后台 新增发布证书&#xff0c;具体操作可查看申请发布证书 申请发布Profile证书 第二招&#xff1a;在IDE中填写 第三招&#xff1a;打包【⚠️发布上架的只能是Build App】 终端展示这一片绿&#xf…

网络安全概论——身份认证

一、身份证明 身份证明可分为以下两大类 身份验证——“你是否是你所声称的你&#xff1f;”身份识别——“我是否知道你是谁&#xff1f;” 身份证明系统设计的三要素&#xff1a; 安全设备的系统强度用户的可接受性系统的成本 实现身份证明的基本途径 所知&#xff1a;个…

【学习记录】浏览器指纹相关学习记录(指纹介绍、获取指纹、修改指纹、随机指纹保护隐私等)

用途 不需要用户登录&#xff0c;可以识别是同一个用户&#xff0c;用于反爬虫广告推送等一类的场景 指纹在线查询地址 http://www.fingerprintbrowser.com/ CreepJS 浏览器指纹在线检测网站:代理IP防关联伪装度查询工具 IP检测大师 【自动化】Python SeleniumUtil 工具 开…

redis数据转移

可能有时候因为硬件的原因我们我们需要更换服务器&#xff0c;如果更换服务器的话&#xff0c;那我们redis的数据该怎样转移呢&#xff0c;按照一下步骤即可完成redis数据的转移 1.进入redis客户端 2.使用 bgsave命令进行数据的备份&#xff0c;此命令完成后会在你的redis安装目…

【MySQL】数据库 Navicat 可视化工具与 MySQL 命令行基本操作

&#x1f4af; 欢迎光临清流君的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落 &#x1f4af; &#x1f525; 个人主页:【清流君】&#x1f525; &#x1f4da; 系列专栏: 运动控制 | 决策规划 | 机器人数值优化 &#x1f4da; &#x1f31f;始终保持好奇心&…

腾讯云智能结构化OCR:以多模态大模型技术为核心,推动跨行业高效精准的文档处理与数据提取新时代

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大三学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

登山第十六梯:深度恢复——解决机器人近视问题

文章目录 一 摘要 二 资源 三 内容 一 摘要 深度感知是基于 3D 视觉的机器人技术的一个重要问题。然而&#xff0c;现实世界的主动立体或 ToF 深度相机经常会产生嘈杂且深度不完整&#xff0c;从而成为机器人性能的瓶颈。在这项工作中&#xff0c;提出了 一个基于学习的立体…

Leetcode中最常用的Java API——util包

前言&#xff1a;在刷力扣的时候是核心代码模式&#xff0c;笔试的时候很可能是ACM模式&#xff0c;需要自己完成导包、定义和自行设计输出&#xff0c;所以一些常用的类和方法需要先导入相应的API包&#xff0c;java.util就是最常用到的包&#xff0c;因为它包含集合这个大框架…

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

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

前端使用 Konva 实现可视化设计器(20)- 性能优化、UI 美化

这一章主要分享一下使用 Konva 遇到的性能优化问题&#xff0c;并且介绍一下 UI 美化的思路。 至少有 2 位小伙伴积极反馈&#xff0c;发现本示例有明显的性能问题&#xff0c;一是内存溢出问题&#xff0c;二是卡顿的问题&#xff0c;在这里感谢大家的提醒。 请大家动动小手&a…

AIGC-------AI生成内容如何赋能AR和VR体验?

AI生成内容如何赋能AR和VR体验 引言 增强现实&#xff08;AR&#xff09;和虚拟现实&#xff08;VR&#xff09;技术近年来蓬勃发展&#xff0c;为用户提供了沉浸式的体验。这些技术已经广泛应用于游戏、教育、医疗、建筑等领域。然而&#xff0c;AR和VR体验的质量与内容的丰富…

VLM--CLIP作分类任务的损失函数

info_nce_loss 这个是clip作对比学习的损失函数 各个博客上都有详细介绍了&#xff0c;我这里就不赘述 def info_nce_loss(image_features, text_features,logit_scale,labels, temperature0.07):batch_size image_features.shape[0]image_features image_features / image…

【模型压缩】原理及实例

在移动智能终端品类越发多样的时代&#xff0c;为了让模型可以顺利部署在算力和存储空间都受限的移动终端&#xff0c;对模型进行压缩尤为重要。模型压缩&#xff08;model compression&#xff09;可以降低神经网络参数量&#xff0c;减少延迟时间&#xff0c;从而实现提高神经…

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

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

Burp与其他安全工具联动及代理设置教程

Burp Suite 是一款功能强大的 Web 安全测试工具&#xff0c;其流量拦截和调试功能可以与其他安全工具&#xff08;如 Xray、Yakit、Goby 等&#xff09;实现联动&#xff0c;从而提升渗透测试的效率。本文将详细讲解 Burp 与其他工具联动的原理以及代理设置的操作方法&#xff…

文件操作(File类)

目录 一、初识文件 二、File类 常用方法 一、初识文件 我们目前是如何存储数据的?弊端是什么? int a 1; int[] arr new int[5];我们这些数据是在内存中存储的&#xff0c;是不能够长久保存的。 那么&#xff0c;我们的计算机当中有没有一块硬件可以长久存储数据的? 磁…

Ubuntu硬盘分区及挂载(命令行)

文章目录 一、简介二、硬盘分区三、格式化分区四、自动挂载分区五、调整分区大小小结 一、简介 创建磁盘分区首先需要找出Linux系统中的物理磁盘&#xff0c;在Linux中采用了一种标准格式来为硬盘分配设备名称。 SATA驱动器和SCSI驱动器&#xff1a;设备命名格式为/dev/sdx&a…