Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> 關於 Linux

Linux setitimer 高精度定時器完整使用指南與範例

編輯:關於 Linux

setitimer 是 Linux 提供的進程級高精度定時器介面,支援三種計時模式,能在微秒級觸發訊號,適用於定時任務、效能分析、多媒體同步等場景。本文詳細解析 API、參數結構、訊號機制並提供完整可編譯範例。

一、核心概念:三種計時器

計時器類型宏常數計時域觸發訊號典型用途
實時計時器ITIMER_REAL牆鐘時間 (wall-clock)SIGALRM一般定時任務、閒置檢測
虛擬計時器ITIMER_VIRTUAL進程用戶態 CPU 時間SIGVTALRM使用者程式碼效能分析
剖析計時器ITIMER_PROF進程用戶態+核心態 CPU 時間SIGPROF全稱效能剖析 (含系統呼叫)

關鍵限制:每個進程同一時間只能擁有一個 setitimer 定時器,後設定會覆蓋前設定。需多定時器請自行實現 (如 timerfd、epoll + 事件循環)。

二、API 原型與結構體

#include <sys/time.h>

int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);

結構體定義:

struct itimerval {
    struct timeval it_interval;  // 週期間隔 (觸發後自動重裝載)
    struct timeval it_value;     // 初次觸發倒數
};

struct timeval {
    long tv_sec;   // 秒
    long tv_usec;  // 微秒 (10^-6 秒)
};
  • it_value:首次倒數歸零觸發訊號,若為 0 則停用定時器。
  • it_interval:非 0 時,觸發後自動重載此值實現週期性觸發;為 0 則僅觸發一次。

三、完整範例:每秒列印 "Hello World"

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/time.h>
#include <errno.h>

void timer_handler(int signo) {
    // 訊號處理函數務必保持簡短、非阻塞、可重入
    write(STDOUT_FILENO, "Hello World\n", 12);
}

int main() {
    // 1. 註冊訊號處理
    signal(SIGALRM, timer_handler);

    // 2. 設定定時器參數
    struct itimerval tick = {0};
    tick.it_value.tv_sec = 2;        // 2 秒後首次觸發
    tick.it_value.tv_usec = 0;
    tick.it_interval.tv_sec = 1;     // 之後每 1 秒觸發
    tick.it_interval.tv_usec = 0;

    // 3. 啟動 ITIMER_REAL 定時器
    if (setitimer(ITIMER_REAL, &tick, NULL) == -1) {
        perror("setitimer failed");
        return -1;
    }

    printf("Timer started. Press Enter to exit...\n");
    getchar();  // 等待使用者輸入結束

    // 4. 停用定時器 (可選)
    struct itimerval zero = {0};
    setitimer(ITIMER_REAL, &zero, NULL);
    return 0;
}

編譯執行:

gcc -o timer_demo timer_demo.c
./timer_demo

四、錯誤碼對照

errno宏原因
EFAULTBad addressvalue 或 ovalue 指標無效
EINVALInvalid argumentwhich 非三種合法類型,或 tv_usec ≥ 1,000,000

五、進階注意事項

  1. 訊號處理函數安全:僅呼叫 Async-signal-safe functions (如 write、_exit),嚴禁 printf、malloc、pthread_mutex_lock 等。
  2. 訊號遺失風險:若處理函數執行時間超過週期,訊號可能合併/遺失 (標準訊號不排隊)。高可靠需求請改用 timer_create + SIGRTMIN (即時訊號支援排隊)。
  3. 多執行緒:訊號預設傳遞給主執行緒,可用 pthread_sigmask 控制。
  4. 精度上限:受限於系統時鐘頻率 (HZ,通常 100~1000Hz),實際精度約 1~10ms;微秒級參數會被向上取整。納秒級需求請用 timer_create + CLOCK_MONOTONIC。

六、替代方案對比

介面精度多定時器訊號排隊複雜度
setitimer~1ms❌ (單一)❌低
timer_create (POSIX Timer)納秒級✅✅ (SIGRT)中
timerfd (Linux 專用)納秒級✅✅ (epoll 整合)中
sleep/usleep/nanosleep毫秒~微秒N/A (阻塞)N/A極低

setitimer 雖屬經典介面,但在現代高併發、高精度場景下,建議優先考慮 timerfd + epoll 事件驅動模型,獲得更好的擴展性與精度控制。

Copyright © Windows教程網 All Rights Reserved