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

Linux定时器机制实现循环确定时间

前言

        想要实现每循环2个小时就做一次业务处,我的简单思路是直接sleep(2*60*60),但是这样感觉不太好,相当于整个线程会卡在这儿,另一个思路是使用time_t不间断的查询时间进行比较,判断是否达到两小时时间,如下:

static void *update_monitor(void *arg)
{
	pthread_detach(pthread_self());
	time_t before_time = time(NULL);
	int interval_time = 2*60*60;
	while(g_mqtt_param.update_flag){
		time_t after_time = time(NULL);
		if(after_time - before_time >= interval_time){
			// 业务操作
			
			before_time = time(NULL);
		}
		sleep(60);
	}
}

解决

使用定时器机制可以更精确地控制任务的执行,而不是每隔固定时间进行 sleep。在 C 语言中,我们可以使用 POSIX 定时器 (timer_create, timer_settime) 来实现定时任务。这个机制相较于使用 sleep() 或者忙等待(polling)更高效,因为它不会阻塞线程,且定时精度高。

下面我会给你一个如何使用定时器机制来每 2 小时执行一次更新子设备操作的示例。

定时器机制实现示例

我们将使用 timer_create() 创建一个定时器,使用 timer_settime() 设置定时器的触发间隔,并用信号处理函数来处理定时器超时事件。

#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

#define UPDATE_INTERVAL 2 * 60 * 60  // 2 hours in seconds

// 定时器标志,用于控制循环退出
volatile sig_atomic_t timer_expired = 0;

// 定时器到期时的处理函数
void timer_handler(int signum) {
    // 定时器到期时会触发此信号
    timer_expired = 1;
}

void update_sub_device() {
    // 注册定时器信号处理函数
    struct sigaction sa;
    sa.sa_handler = timer_handler;  // 定义定时器到期时的处理函数
    sa.sa_flags = SA_RESTART;
    sigaction(SIGALRM, &sa, NULL);  // SIGALRM 是定时器到期时会发送的信号

    // 创建定时器
    timer_t timerid;
    struct itimerspec its;
    its.it_value.tv_sec = UPDATE_INTERVAL;   // 设置定时器初始超时为2小时
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = UPDATE_INTERVAL;  // 设置定时器间隔为2小时
    its.it_interval.tv_nsec = 0;

    // 创建定时器
    if (timer_create(CLOCK_REALTIME, NULL, &timerid) == -1) {
        perror("timer_create");
        exit(EXIT_FAILURE);
    }

    // 启动定时器
    if (timer_settime(timerid, 0, &its, NULL) == -1) {
        perror("timer_settime");
        exit(EXIT_FAILURE);
    }

    // 模拟主程序的其他逻辑
    while (1) {
        if (timer_expired) {
            // 2小时到期后,执行更新子设备的操作
            printf("Updating sub-device...\n");

            // 重置定时器标志
            timer_expired = 0;

            // 重新启动定时器
            if (timer_settime(timerid, 0, &its, NULL) == -1) {
                perror("timer_settime");
                exit(EXIT_FAILURE);
            }
        }

        // 可以在这里添加其他业务逻辑
        sleep(1);  // 主程序空闲时可以执行其他任务
    }
}

int main() {
    update_sub_device();
    return 0;
}

代码解析:

  1. 定时器信号处理

    • 我们使用 sigaction() 注册了一个信号处理器,当定时器超时时,它会发送 SIGALRM 信号,信号处理函数 timer_handler 会被触发。
    • timer_expired 变量作为标志,指示定时器是否到期。
  2. 创建定时器

    • timer_create() 创建了一个定时器,它需要一个时钟(此处使用 CLOCK_REALTIME)和一个 timer_t 类型的定时器ID。
    • timer_settime() 设置定时器的超时和间隔时间,it_value 是第一次触发的时间,it_interval 是定时器的周期。
  3. 定时器执行

    • 在主循环中,我们检查 timer_expired 标志。如果标志为 1,说明定时器已到期,此时执行更新子设备的操作。
    • 操作完成后,我们将 timer_expired 置为 0,并使用 timer_settime() 重新启动定时器,确保下次定时器再到期时执行操作。
  4. 信号和处理函数

    • 当定时器到期时,它会发送一个 SIGALRM 信号,我们的信号处理函数 timer_handler() 会被触发,标记 timer_expired 为 1

优势:

  • 高效性:使用定时器不需要在程序中使用 sleep() 来延时,避免了忙等待或长时间阻塞。
  • 精确控制:定时器机制能够提供精确的时间间隔,能够处理精确到秒的定时任务。

注意事项:

  • 信号处理:信号处理函数是异步执行的,需要确保它的执行尽可能简单,不要执行耗时操作。复杂的操作应该通过设置标志来交给主线程处理。
  • 错误处理:在实际的生产环境中,要更加注意定时器相关函数的错误处理,确保定时器的正确创建和启动。

总结:

使用 POSIX 定时器可以使程序更加高效和精确地执行定时任务。相比于使用 sleep(),它能够提供更好的时间管理,并且避免了因忙等待导致的资源浪费。

 


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

相关文章:

  • sqlmap使用过程中的每个步骤及其相关命令
  • 微信小程序蓝牙writeBLECharacteristicValue写入数据返回成功后,实际硬件内信息查询未存储?
  • C语言:深入理解指针
  • 什么是串联谐振
  • 路由引入中次优路由和路由环路问题
  • Reachy 2,专为AI与机器人实验室打造的卓越开源双臂移动操作平台!
  • 使用 OpenCV 进行视频中的行人检测
  • 【Web前端】如何构建简单HTML表单?
  • Vue 路由配置与环境差异问题解析:开发与生产环境中的行为差异
  • 大数据新视界 -- Hive 函数应用:复杂数据转换的实战案例(下)(12/ 30)
  • 解决 Vim 上下左右变成 ABCD 的问题
  • 技术总结(四十)
  • springboot331“有光”摄影分享网站系统pf(论文+源码)_kaic
  • CTF-RE 从0到 N: 高版本 APK 调试 + APK逻辑修改再打包 + os层调试[2024 强网杯青少年专项赛 Flip_over] writeup
  • 50-基于单片机和传感器的冷链运输设计
  • 实战丨证券 HTAP 混合业务场景的难点问题应对
  • python代码示例(读取excel文件,自动播放音频)
  • Flink (Windows Function 窗口函数)
  • [Maven]3.5.3配置
  • HTTP超文本协议
  • Python轴承故障诊断 (21)基于VMD-CNN-BiTCN的创新诊断模型
  • C++练级计划-> 《IO流》iostream fstream sstream详解
  • 操作系统 | 学习笔记 | 王道 | 2.1 进程与线程
  • 若依前端报错 components.at is not a function
  • JVM(JAVA虚拟机)内存溢出导致内存不足,Java运行时环境无法继续
  • 外卖点餐系统小程序