函数概述
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;
}
重要注意事项
-
信号安全: 定时器处理函数中只能使用异步信号安全的函数
-
精度限制: 实际精度受系统时钟粒度限制,通常为10ms左右
-
资源限制: 每个进程每种类型的定时器只能有一个
-
继承关系: 子进程不继承父进程的定时器设置
常见错误处理
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()
提供了更强大和灵活的定时器功能,特别适合需要高精度或周期性定时的应用场景。