C语言中的setitimer函数详解

函数概述

setitimer()是一个用于设置间隔定时器的系统调用函数,它提供了比alarm()函数更精确的定时控制。

函数原型

cpp 复制代码
#include <sys/time.h>

int setitimer(int which, const struct itimerval *new_value,
              struct itimerval *old_value);

参数详解

1. which - 定时器类型

  • ITIMER_REAL : 真实时间定时器,到期时发送SIGALRM信号

  • ITIMER_VIRTUAL : 虚拟时间定时器(进程在用户态执行的时间),到期时发送SIGVTALRM信号

  • ITIMER_PROF : profiling定时器(进程在用户态和内核态执行的时间),到期时发送SIGPROF信号

2. new_value - 新定时器值

指向struct itimerval结构的指针,包含:

cpp 复制代码
struct itimerval {
    struct timeval it_interval; /* 定时器间隔 */
    struct timeval it_value;    /* 第一次到期时间 */
};

struct timeval {
    time_t      tv_sec;         /* 秒 */
    suseconds_t tv_usec;        /* 微秒 */
};

3. old_value - 旧定时器值

如果不为NULL,则返回之前的定时器设置

返回值

  • 成功:返回0

  • 失败:返回-1,并设置errno

使用示例

示例1:基本定时器使用

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>

void timer_handler(int signum) {
    static int count = 0;
    printf("定时器到期: %d\n", ++count);
}

int main() {
    struct itimerval timer;
    
    // 设置信号处理函数
    signal(SIGALRM, timer_handler);
    
    // 配置定时器:1秒后第一次触发,之后每2秒触发一次
    timer.it_value.tv_sec = 1;
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 2;
    timer.it_interval.tv_usec = 0;
    
    // 启动定时器
    if (setitimer(ITIMER_REAL, &timer, NULL) == -1) {
        perror("setitimer");
        exit(1);
    }
    
    // 主循环
    while (1) {
        pause(); // 等待信号
    }
    
    return 0;
}

示例2:高精度定时器

cpp 复制代码
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>

void high_precision_handler(int sig) {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    printf("高精度定时: %ld.%06ld\n", tv.tv_sec, tv.tv_usec);
}

int main() {
    struct itimerval timer;
    
    signal(SIGALRM, high_precision_handler);
    
    // 设置500毫秒间隔
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = 500000;  // 500ms
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 500000;
    
    setitimer(ITIMER_REAL, &timer, NULL);
    
    // 运行5秒
    sleep(5);
    
    // 关闭定时器
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = 0;
    setitimer(ITIMER_REAL, &timer, NULL);
    
    return 0;
}

示例3:多种定时器类型

cpp 复制代码
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>

void real_handler(int sig) {
    printf("真实时间定时器触发\n");
}

void virtual_handler(int sig) {
    printf("虚拟时间定时器触发\n");
}

void prof_handler(int sig) {
    printf("Profiling定时器触发\n");
}

int main() {
    struct itimerval timer;
    
    signal(SIGALRM, real_handler);
    signal(SIGVTALRM, virtual_handler);
    signal(SIGPROF, prof_handler);
    
    // 设置真实时间定时器
    timer.it_value.tv_sec = 1;
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 1;
    timer.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &timer, NULL);
    
    // 设置虚拟时间定时器
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = 500000;
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 500000;
    setitimer(ITIMER_VIRTUAL, &timer, NULL);
    
    // 运行一些计算消耗CPU时间
    volatile int i;
    for (i = 0; i < 1000000000; i++);
    
    return 0;
}

重要注意事项

  1. 信号安全: 定时器处理函数中只能使用异步信号安全的函数

  2. 精度限制: 实际精度受系统时钟粒度限制,通常为10ms左右

  3. 资源限制: 每个进程每种类型的定时器只能有一个

  4. 继承关系: 子进程不继承父进程的定时器设置

常见错误处理

cpp 复制代码
#include <errno.h>
#include <string.h>

// 设置定时器并检查错误
if (setitimer(ITIMER_REAL, &timer, NULL) == -1) {
    switch(errno) {
        case EFAULT:
            printf("参数指向非法地址\n");
            break;
        case EINVAL:
            printf("which参数无效或时间值无效\n");
            break;
        default:
            printf("setitimer错误: %s\n", strerror(errno));
    }
    exit(1);
}

与alarm()的比较

特性 alarm() setitimer()
精度 秒级 微秒级
重复触发 不支持 支持
定时器类型 只有真实时间 三种类型
灵活性 低 高

setitimer()提供了更强大和灵活的定时器功能,特别适合需要高精度或周期性定时的应用场景。

相关推荐
怕浪猫7 小时前
GEO 优化到底是什么?AI时代内容创作者必须懂的新技能
算法·面试·github
朝朝辞暮i8 小时前
C++ 第 23 课:class —— 开始真正进入面向对象
开发语言·c++·算法
Evand J9 小时前
【MATLAB例程】三维RRT+APF避障路径规划与到达角(AOA)定位算法|三维路径优化与定位仿真例程
算法·matlab·路径规划·代码·定位·rrt·aoa
小师兄吃牛肉9 小时前
C语言篇:宏
c语言·开发语言
郑同学的笔记9 小时前
【c++随笔28】strcmp 和 memcmp对比
开发语言·c++
炸膛坦客10 小时前
单片机开发工具篇:(十四)配置输出 .map 文件及其本地路径
c语言·单片机·嵌入式硬件
言乐610 小时前
Python根据无法识别搜索词找出可能输入内容模型
开发语言·python·django·virtualenv·pygame
weixin_3077791310 小时前
有限产能智能排产与动态重排智能体:从需求解构到技术实现
开发语言·人工智能·算法·架构
kakakahahahaha10 小时前
Windows C盘临时文件清理:%temp%、Windows Temp、Prefetch、Windows.old与hiberfil.sys处理指南
c语言·开发语言·windows
朝朝辞暮i10 小时前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法