从秒级普通定时到毫秒级精确定时,掌握 UNIX 系统定时机制的核心工具
一、UNIX 定时器的核心定位与分类
在 UNIX 系统中,定时器(Timer) 是实现"定时触发事件"的核心机制,其本质是"内核在指定时间后向进程发送特定信号",进程通过捕获信号执行预设逻辑(如定时任务、超时处理)。根据精度和功能差异,UNIX 定时器主要分为两类:
- 普通定时器(alarm 函数):秒级精度,仅支持"一次定时"或"覆盖式定时",功能简单,适用于对精度要求不高的场景(如超时提醒、简单定时任务);
- 精确定时器(setitimer 函数):理论毫秒级精度,支持三种计时类型(真实时间、用户态时间、用户态+核心态时间)和"重复定时",功能灵活,适用于高精度、复杂定时场景(如性能监控、高频任务调度)。
两种定时器均依赖"信号触发"机制(如 SIGALRM
、SIGVTALRM
),进程需通过信号捕获函数响应定时事件,本质是"异步定时"------定时器触发不阻塞进程主流程,而是通过信号中断实现。
二、普通定时器:alarm 函数的使用
alarm
函数是 UNIX 系统中最基础的定时接口,定义在 <unistd.h>
头文件中,核心功能是"在指定秒数后向进程发送 SIGALRM
信号",仅支持秒级精度和简单定时逻辑。
1. 函数原型与核心参数
c
#include <unistd.h>
// 功能:设置秒级定时器,指定秒数后发送 SIGALRM 信号
// 参数:
// seconds:定时秒数,取值 >= 0;
// - 若 seconds > 0:设置新定时器,seconds 秒后触发;
// - 若 seconds = 0:取消当前已设置的 alarm 定时器。
// 返回值:
// - 成功:返回之前未到期的定时器剩余秒数(若无可返回 0);
// - 失败:返回 -1(极少发生,通常因参数无效)。
unsigned int alarm(unsigned int seconds);
关键特性:
- 覆盖性 :若进程已设置未到期的 alarm 定时器,再次调用
alarm(seconds)
会覆盖原定时器,返回原定时器的剩余秒数; - 一次性 :定时器触发(发送
SIGALRM
)后自动失效,若需重复定时,需在信号捕获函数中重新调用alarm
; - 信号依赖 :定时器触发的核心是
SIGALRM
信号,若进程忽略或未捕获该信号,默认行为是终止进程(需特别注意)。
2. 实战:alarm 函数的典型用法
实例 1:基础定时------3 秒后触发 SIGALRM 信号
以下为规范格式后的代码和说明:
代码部分
c
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
// SIGALRM 信号捕获函数
void sigalrm_handler(int sig) {
printf("捕获到 SIGALRM 信号(定时时间到),程序退出\n");
exit(EXIT_SUCCESS);
}
int main() {
// 1. 捕获 SIGALRM 信号(避免默认终止)
if (signal(SIGALRM, sigalrm_handler) == SIG_ERR) {
perror("signal 注册 SIGALRM 失败");
return 1;
}
// 2. 设置 3 秒后触发定时器
unsigned int remaining = alarm(3);
printf("已设置 3 秒定时器,之前无未到期定时器,返回值:%u\n", remaining);
// 3. 主进程阻塞等待(避免提前退出)
printf("主进程等待定时器触发...\n");
while (1) {
sleep(1);
printf("等待中...\n");
}
return 0;
}
编译与运行
bash
# 1. 编译程序
gcc alarm_basic.c -o alarm_basic
# 2. 运行程序
./alarm_basic
预期输出
已设置 3 秒定时器,之前无未到期定时器,返回值:0
主进程等待定时器触发...
等待中...
等待中...
等待中...
捕获到 SIGALRM 信号(定时时间到),程序退出
实例 2:重复定时------每隔 1 秒触发一次 SIGALRM
c
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
// 全局计数:记录定时触发次数(volatile 避免编译器优化)
volatile int count = 0;
// SIGALRM 捕获函数:重新设置定时器实现重复定时
void sigalrm_handler(int sig) {
count++;
printf("第 %d 次定时触发(每隔 1 秒)\n", count);
// 触发 5 次后退出
if (count >= 5) {
printf("已触发 5 次,程序退出\n");
exit(EXIT_SUCCESS);
}
// 重新设置 1 秒定时器,实现重复触发
alarm(1);
}
int main() {
// 注册 SIGALRM 捕获函数
if (signal(SIGALRM, sigalrm_handler) == SIG_ERR) {
perror("signal 注册失败");
return 1;
}
// 首次设置 1 秒定时器
alarm(1);
printf("重复定时器已启动,每隔 1 秒触发一次(共 5 次)\n");
// 主进程循环等待
while (1) {
pause(); // 阻塞等待信号,比 sleep 更高效
}
return 0;
}
编译与运行
bash
gcc alarm_repeat.c -o alarm_repeat
./alarm_repeat
预期输出
重复定时器已启动,每隔 1 秒触发一次(共 5 次)
第 1 次定时触发(每隔 1 秒)
第 2 次定时触发(每隔 1 秒)
第 3 次定时触发(每隔 1 秒)
第 4 次定时触发(每隔 1 秒)
第 5 次定时触发(每隔 1 秒)
已触发 5 次,程序退出
关键技巧 :使用 pause()
替代 sleep(1)
等待信号,pause()
会一直阻塞直到收到任意信号,避免 sleep
的时间误差,更适合信号驱动的场景。
三、精确定时器:setitimer 函数的使用
setitimer
函数是 UNIX 系统提供的增强型定时接口,定义在 <sys/time.h>
头文件中。相比 alarm 函数,它支持毫秒级精度、三种计时类型和自动重复定时,功能更强大,适用于高精度定时场景。
1. 函数原型与核心参数
c
#include <sys/time.h>
// 功能:设置精确定时器,支持三种类型和重复定时
// 参数:
// which:定时器类型(ITIMER_REAL / ITIMER_VIRT / ITIMER_PROF);
// new_value:新定时器参数(定时时间、重复间隔);
// old_value:非 NULL 时,存储之前定时器的参数(用于恢复);
// 返回值:成功返回 0,失败返回 -1,错误码存入 errno。
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
// 定时器参数结构体:包含"初始定时时间"和"重复间隔时间"
struct itimerval {
struct timeval it_interval; // 重复定时的间隔时间(0 表示仅一次)
struct timeval it_value; // 首次定时的时间(0 表示取消定时器)
};
// 时间结构体:支持秒和微秒(理论精度 1 微秒,实际受系统调度影响)
struct timeval {
time_t tv_sec; // 秒数
suseconds_t tv_usec; // 微秒数(0 ~ 999999)
};
核心概念解析:
struct itimerval
的作用:it_value
:首次触发定时器的时间(如{1, 500000}
表示 1.5 秒后首次触发);it_interval
:首次触发后,重复定时的间隔时间(如{1, 500000}
表示每隔 1.5 秒重复触发;为{0, 0}
表示仅触发一次)。
- 取消定时器 :将
new_value->it_value
设置为{0, 0}
,调用 setitimer 即可取消对应类型的定时器。
2. setitimer 的三种定时器类型
setitimer 支持三种不同的计时类型,对应不同的时间统计范围和触发信号,适用于不同场景:
定时器类型 | 计时范围 | 触发信号 | 核心用途 | 精度影响因素 |
---|---|---|---|---|
ITIMER_REAL |
真实时间(墙钟时间),无论进程是否运行,时间都会累积 | SIGALRM |
通用定时场景(如超时提醒、定时任务调度),与 alarm 函数功能重叠 | 系统负载(高负载时,信号可能延迟送达),理论精度 1 微秒,实际约 10~100 微秒 |
ITIMER_VIRT |
进程在用户态运行的时间(仅统计进程执行用户代码的时间,内核态时间不累积) | SIGVTALRM |
用户态代码性能监控(如统计函数执行耗时、限制用户态运行时间) | 进程调度(仅进程在用户态时计时),精度较高,不受其他进程影响 |
ITIMER_PROF |
进程在用户态 + 核心态运行的总时间(统计进程占用 CPU 的所有时间) | SIGPROF |
进程总 CPU 占用监控(如性能分析、限制进程总 CPU 时间) | CPU 调度(仅进程占用 CPU 时计时),精度与 ITIMER_VIRT 相当 |
3. 实战:setitimer 函数的典型用法
实例 1:ITIMER_REAL 类型------1.5 秒重复定时(真实时间)
c
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>
volatile int count = 0;
// SIGALRM 捕获函数(ITIMER_REAL 触发)
void sigalrm_handler(int sig) {
count++;
printf("第 %d 次定时触发(ITIMER_REAL,间隔 1.5 秒)\n", count);
if (count >= 3) {
printf("已触发 3 次,取消定时器并退出\n");
// 取消 ITIMER_REAL 定时器
struct itimerval cancel_timer = {{0, 0}, {0, 0}};
setitimer(ITIMER_REAL, &cancel_timer, NULL);
exit(EXIT_SUCCESS);
}
}
int main() {
// 1. 捕获 SIGALRM 信号
if (signal(SIGALRM, sigalrm_handler) == SIG_ERR) {
perror("signal 注册失败");
return 1;
}
// 2. 配置定时器参数:首次 1.5 秒,重复间隔 1.5 秒
struct itimerval timer;
// 重复间隔:1 秒 + 500000 微秒 = 1.5 秒
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 500000;
// 首次定时:1.5 秒
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 500000;
// 3. 设置 ITIMER_REAL 定时器
if (setitimer(ITIMER_REAL, &timer, NULL) == -1) {
perror("setitimer 失败");
return 1;
}
printf("ITIMER_REAL 定时器已启动(1.5 秒重复)\n");
// 4. 等待信号
while (1) {
pause();
}
return 0;
}
sh
# 1. 编译程序
gcc setitimer_real.c -o setitimer_real
# 2. 运行程序
./setitimer_real
输出结果
ITIMER_REAL 定时器已启动(1.5 秒重复)
第 1 次定时触发(ITIMER_REAL,间隔 1.5 秒)
第 2 次定时触发(ITIMER_REAL,间隔 1.5 秒)
第 3 次定时触发(ITIMER_REAL,间隔 1.5 秒)
已触发 3 次,取消定时器并退出
实例 2:ITIMER_VIRT 类型------用户态 0.5 秒定时(仅统计用户态时间)
c
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>
volatile int user_time_count = 0;
// SIGVTALRM 捕获函数(ITIMER_VIRT 触发)
void sigvtalrm_handler(int sig) {
user_time_count++;
printf("用户态时间累积 0.5 秒,触发第 %d 次信号\n", user_time_count);
if (user_time_count >= 2) {
printf("用户态总时间已达 1 秒,程序退出\n");
exit(EXIT_SUCCESS);
}
}
int main() {
// 1. 捕获 SIGVTALRM 信号
if (signal(SIGVTALRM, sigvtalrm_handler) == SIG_ERR) {
perror("signal 注册失败");
return 1;
}
// 2. 配置 ITIMER_VIRT 定时器:用户态每累积 0.5 秒触发
struct itimerval timer;
timer.it_interval = (struct timeval){0, 500000}; // 重复间隔 0.5 秒
timer.it_value = (struct timeval){0, 500000}; // 首次 0.5 秒
if (setitimer(ITIMER_VIRT, &timer, NULL) == -1) {
perror("setitimer 失败");
return 1;
}
printf("ITIMER_VIRT 定时器已启动(用户态每 0.5 秒触发)\n");
// 3. 执行用户态计算(模拟用户态耗时操作)
printf("开始执行用户态计算...\n");
unsigned long long sum = 0;
while (1) {
sum++; // 纯用户态操作,累积用户态时间
}
return 0;
}
编译与运行命令
bash
gcc setitimer_virt.c -o setitimer_virt
./setitimer_virt
预期输出
ITIMER_VIRT 定时器已启动(用户态每 0.5 秒触发)
开始执行用户态计算...
用户态时间累积 0.5 秒,触发第 1 次信号
用户态时间累积 0.5 秒,触发第 2 次信号
用户态总时间已达 1 秒,程序退出
关键结论:ITIMER_VIRT 仅统计用户态时间------若进程因 I/O 阻塞进入睡眠(非用户态),计时会暂停;只有进程执行用户代码时,时间才会累积,适合精准统计用户态代码的运行时长。
四、alarm 与 setitimer 的对比与相互影响
alarm 和 setitimer(尤其是 ITIMER_REAL 类型)在功能上存在重叠,但在精度、灵活性和适用场景上差异显著。同时,两者存在相互影响,使用时需特别注意避免冲突。
1. 核心功能对比
对比维度 | alarm 函数 | setitimer 函数(ITIMER_REAL) | setitimer 函数(ITIMER_VIRT/ITIMER_PROF) |
---|---|---|---|
精度 | 秒级(最低 1 秒) | 毫秒级(理论 1 微秒,实际 10~100 微秒) | 毫秒级 |
定时类型 | 仅真实时间(墙钟时间) | 真实时间 | 用户态时间 / 用户态+核心态时间 |
重复定时 | 需手动在信号处理函数中重新调用 | 支持自动重复(通过 it_interval 设置) | 支持自动重复 |
触发信号 | SIGALRM | SIGALRM | SIGVTALRM / SIGPROF |
参数复杂度 | 简单(仅需秒数) | 复杂(需配置 struct itimerval) | 复杂 |
适用场景 | 简单秒级定时(如超时提醒、基础定时任务) | 高精度真实时间定时(如高频任务调度、精准超时控制) | 进程 CPU 时间监控(如性能分析、CPU 时间限制) |
优点 | 使用简单、代码侵入性低 | 精度高、支持自动重复、功能灵活 | 精准统计 CPU 时间、不受系统负载影响 |
缺点 | 精度低、不支持自动重复 | 参数复杂、受系统负载影响精度 | 仅统计 CPU 时间、不适合真实时间定时 |
2. 相互影响:不可同时使用的场景
核心冲突:alarm 与 ITIMER_REAL 共享 SIGALRM 信号:
alarm 函数和 setitimer 的 ITIMER_REAL 类型均通过 SIGALRM
信号触发,且共享同一内核定时器资源------若进程同时使用两者,会产生以下冲突:
- 覆盖冲突 :调用
alarm(seconds)
会覆盖已设置的 ITIMER_REAL 定时器,反之亦然;例如,先通过 setitimer 设置 ITIMER_REAL 定时,再调用alarm(5)
,原 ITIMER_REAL 定时器会被取消; - 信号混淆 :
SIGALRM
信号触发后,进程无法区分是来自 alarm 还是 ITIMER_REAL,可能导致逻辑错误; - 精度丢失:alarm 是秒级精度,会降低 ITIMER_REAL 的毫秒级精度优势。
解决方法 :同一进程中,禁止同时使用 alarm 函数和 ITIMER_REAL 类型的 setitimer;若需高精度定时,优先使用 setitimer(ITIMER_REAL);若需简单定时,使用 alarm,二者择一。
无冲突场景 :alarm 与 ITIMER_VIRT/ITIMER_PROF 无冲突------这两种 setitimer 类型分别触发 SIGVTALRM
和 SIGPROF
信号,与 alarm 的 SIGALRM
信号独立,可同时使用。
冲突演示:alarm 覆盖 ITIMER_REAL 定时器
c
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
void sigalrm_handler(int sig) {
printf("捕获到 SIGALRM 信号(来自 alarm,而非 ITIMER_REAL)\n");
exit(EXIT_SUCCESS);
}
int main() {
signal(SIGALRM, sigalrm_handler);
// 1. 先设置 ITIMER_REAL 定时器(1.5 秒触发)
struct itimerval timer = {
{0, 0}, // 仅一次定时,无重复
{1, 500000} // 1.5 秒后触发
};
if (setitimer(ITIMER_REAL, &timer, NULL) == -1) {
perror("setitimer 失败");
return 1;
}
printf("已设置 ITIMER_REAL 定时器(1.5 秒后触发)\n");
// 2. 1 秒后调用 alarm(2),覆盖 ITIMER_REAL
sleep(1);
alarm(2);
printf("1 秒后调用 alarm(2),覆盖 ITIMER_REAL 定时器\n");
// 等待信号
while (1) {
pause();
}
return 0;
}
已设置 ITIMER_REAL 定时器(1.5 秒后触发)
1 秒后调用 alarm(2),覆盖 ITIMER_REAL 定时器
捕获到 SIGALRM 信号(来自 alarm,而非 ITIMER_REAL)
结论:ITIMER_REAL 定时器被 alarm 覆盖,最终触发的 SIGALRM 来自 alarm,证明二者存在冲突,不可同时使用。
五、定时器使用的常见错误与解决方法
在使用 alarm 或 setitimer 时,易因参数配置、信号处理或类型选择错误导致定时失效、程序崩溃等问题。以下是高频错误及解决方法:
常见错误 | 问题现象 | 原因分析 | 解决方法 |
---|---|---|---|
未捕获定时器信号,程序被终止 | 定时器触发后,程序无任何提示直接退出,终端显示"Terminated" | 定时器触发的信号(如 SIGALRM、SIGVTALRM)默认处理动作是"终止进程",若进程未捕获或忽略这些信号,会被系统终止 | 1. 必须通过 signal 或 sigaction 注册信号捕获函数,自定义信号处理逻辑; 2. 示例: if (signal(SIGALRM, handler) == SIG_ERR) { perror("signal 失败"); } 3. 若无需处理信号,可忽略信号(不推荐,可能丢失定时事件): signal(SIGALRM, SIG_IGN); |
setitimer 参数结构体初始化错误 | 定时器未按预期触发(如定时时间偏差大、不重复触发),或 setitimer 调用失败 | 1. 未初始化 struct itimerval 或 struct timeval ,存在垃圾数据(如 tv_usec 为负数或超过 999999); 2. 混淆 it_interval 和 it_value 的作用(如将重复间隔设为 it_value,导致仅触发一次); 3. tv_usec 取值超出范围(应在 0~999999 之间) |
1. 显式初始化结构体,避免垃圾数据: struct itimerval timer = {``{1, 0}, {2, 0}}; (推荐)或 memset(&timer, 0, sizeof(timer)); 2. 明确参数含义: - it_value:首次触发时间(必须设置,否则定时器不生效); - it_interval:重复间隔(0 表示仅一次); 3. 确保 tv_usec 取值合法(0 ≤ tv_usec ≤ 999999),避免整数溢出 |
alarm 重复定时时未重新调用 | alarm 定时器仅触发一次,后续无信号触发 | alarm 是"一次性"定时器,触发后自动失效;若需重复定时,需在信号捕获函数中重新调用 alarm(seconds) ,否则仅触发一次 |
在 SIGALRM 信号捕获函数中重新设置 alarm,实现重复定时: void handler(int sig) { alarm(1); /* 其他逻辑 */ } 注意:重新调用的时间应与预期间隔一致,避免累积误差 |
定时器精度低于预期(如毫秒级定时偏差大) | setitimer(ITIMER_REAL) 设置 100ms 定时,实际触发间隔为 120~150ms,偏差超过 20% | 1. 系统负载过高:高负载时,内核调度延迟,信号无法及时送达; 2. 进程阻塞:进程因 I/O、sleep 等操作阻塞,错过信号处理时机; 3. 硬件精度限制:部分嵌入式系统或老旧硬件的时钟精度不足,无法支持毫秒级定时 | 1. 降低系统负载:关闭无用进程,减少资源竞争; 2. 避免进程长时间阻塞:使用非阻塞 I/O,减少 sleep 调用; 3. 选择合适的定时类型:若需精准 CPU 时间统计,改用 ITIMER_VIRT/ITIMER_PROF(不受系统负载影响); 4. 硬件层面优化:在嵌入式系统中,选择高精度时钟硬件(如 RTC 实时时钟) |
同时使用 alarm 和 ITIMER_REAL,导致定时混乱 | 定时器触发时间与预期不符,或信号处理逻辑错乱(无法区分信号来源) | alarm 和 ITIMER_REAL 共享 SIGALRM 信号和内核定时器资源,同时使用会相互覆盖,导致定时逻辑混乱 | 1. 同一进程中禁止同时使用 alarm 和 ITIMER_REAL,二者择一; 2. 若需高精度定时,优先使用 setitimer(ITIMER_REAL);若需简单秒级定时,使用 alarm; 3. 若需同时处理真实时间和 CPU 时间定时,使用 setitimer(ITIMER_REAL) + setitimer(ITIMER_VIRT),避免使用 alarm |
六、定时器的实际应用场景
定时器在 UNIX 程序开发中应用广泛,尤其在服务端程序、性能监控、嵌入式系统中,是实现定时任务、超时控制的核心工具。以下是典型应用场景:
1. 服务端程序的超时控制
服务端程序(如 Web 服务器、数据库)在处理客户端请求时,需设置超时时间(如 30 秒无响应则断开连接),避免因客户端异常导致资源长期占用。
实现方案:
- 使用
setitimer(ITIMER_REAL, ...)
设置超时时间(如 30 秒); - 客户端请求处理完成前,若收到
SIGALRM
信号,判定为超时,关闭连接并释放资源; - 请求正常处理完成后,取消定时器(设置 it_value 为 {0, 0})。
优势:ITIMER_REAL 的毫秒级精度可实现精准超时控制,避免误判;自动重复定时可简化多请求场景的超时管理。
2. 定时任务调度
系统工具或应用程序需定期执行任务(如日志轮转、数据备份、状态上报),需通过定时器实现周期性触发。
实现方案:
- 简单场景(秒级间隔):使用 alarm 函数,在 SIGALRM 捕获函数中重新调用 alarm,实现重复定时;
- 复杂场景(毫秒级间隔、多任务):使用 setitimer(ITIMER_REAL),通过不同信号(如 SIGALRM、SIGVTALRM)区分不同定时任务;
- 示例:日志系统每隔 1 小时轮转日志,通过 setitimer 设置 ITIMER_REAL 定时,触发后执行日志重命名和压缩逻辑。
优势:无需额外线程,通过信号异步触发,不阻塞主流程,资源占用低。
3. 性能监控与分析
性能分析工具(如 gprof
)需统计程序的 CPU 时间占用(用户态、核心态),或定期采样程序运行状态,用于定位性能瓶颈。
实现方案:
- 统计用户态时间:使用
setitimer(ITIMER_VIRT, ...)
,定时触发 SIGVTALRM 信号,记录当前执行的函数栈; - 统计总 CPU 时间:使用
setitimer(ITIMER_PROF, ...)
,同时记录用户态和核心态时间占比; - 示例:性能工具每隔 10ms 采样一次函数调用栈,通过 ITIMER_VIRT 定时实现,生成 CPU 占用热力图。
优势:ITIMER_VIRT/ITIMER_PROF 精准统计 CPU 时间,不受系统负载影响,是性能分析的核心工具。
4. 嵌入式系统的实时控制
嵌入式系统(如工业控制、智能家居)需实时响应外部事件(如传感器数据采集、设备控制),需毫秒级甚至微秒级定时。
实现方案:
- 高精度定时:使用
setitimer(ITIMER_REAL, ...)
,结合硬件时钟,实现 10~100 微秒级定时; - 任务调度:通过多个定时器(如 ITIMER_REAL 用于设备控制,ITIMER_VIRT 用于数据处理),实现多任务并发调度;
- 示例:温度传感器每隔 500ms 采集一次数据,通过 setitimer(ITIMER_REAL) 定时触发采集逻辑。
优势:setitimer 的高精度和灵活类型,满足嵌入式系统的实时性需求,资源占用低,适合资源受限的场景。
UNIX 系统中两种核心定时器(alarm 和 setitimer)的使用方法、参数配置、类型差异,对比了二者的优缺点和适用场景,分析了常见错误与解决方法,并介绍了实际应用场景。alarm 函数简单易用,适合秒级普通定时;setitimer 函数功能强大,支持毫秒级精度和多种计时类型,适合高精度、复杂定时场景。
在实际开发中,需根据需求选择合适的定时器:
- 简单秒级定时(如超时提醒)→ 选择 alarm 函数,代码简洁;
- 高精度真实时间定时(如服务端超时控制)→ 选择 setitimer(ITIMER_REAL);
- CPU 时间统计(如性能监控)→ 选择 setitimer(ITIMER_VIRT/ITIMER_PROF);
- 禁止同时使用 alarm 和 ITIMER_REAL,避免信号和定时器冲突。
掌握定时器的使用,是编写高效、健壮 UNIX 程序的基础,尤其在服务端开发和嵌入式领域,定时器是实现定时任务、超时控制、性能监控的核心工具。