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、select、nanosleep 完全指南

編輯:Linux 教學

前言

sleep() 僅支援秒級休眠,無法滿足高精度需求。Linux 提供多種微秒/奈秒級休眠方案:setitimer() 間隔定時器、select() 超時機制、usleep()、nanosleep()。本文詳細比較其原理、精度與適用場景。

1. setitimer() 間隔定時器

#include <sys/time.h>
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

三種定時器類型

常數說明信號
ITIMER_REAL真實時間 (牆鐘時間),最常用SIGALRM
ITIMER_VIRTUAL進程用戶態 CPU 時間SIGVTALRM
ITIMER_PROF進程用戶態+核心態 CPU 時間SIGPROF

時間結構

struct itimerval {
    struct timeval it_interval;  // 間隔週期 (週期性觸發)
    struct timeval it_value;     // 初始延遲 / 下次觸發剩餘時間
};
struct timeval {
    time_t      tv_sec;   // 秒
    suseconds_t tv_usec;  // 微秒 (0~999999)
};

休眠範例 (單次)

void ms_sleep(long ms) {
    struct itimerval it = { .it_value = { .tv_sec = ms/1000, .tv_usec = (ms%1000)*1000 } };
    setitimer(ITIMER_REAL, &it, NULL);
    pause();  // 等待 SIGALRM
}

缺點

  • 進程僅能擁有 3 個定時器 (對應三種類型),資源有限。
  • 需設置信號處理函數,pause() 會被任何信號喚醒,需重新檢查時間。
  • 信號處理上下文切換開銷大。

2. select() / pselect() 超時休眠 (推薦)

#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

微秒級休眠封裝

int us_sleep(long us) {
    struct timeval tv = { .tv_sec = us / 1000000, .tv_usec = us % 1000000 };
    return select(0, NULL, NULL, NULL, &tv);
}

優點

  • 無需信號,不佔用定時器資源。
  • 精度達微秒級 (受限於系統時鐘中斷頻率 HZ,現代核心動態滴答可達高精度)。
  • 可被信號中斷 (EINTR),易於整合事件迴圈。

3. usleep() 與 nanosleep()

函數精度標準備註
usleep(useconds_t)微秒BSD / POSIX.1-2001 (標記過時)內部常用 nanosleep() 實現
nanosleep(const struct timespec *, struct timespec *)奈秒POSIX.1b (即時擴展)支援剩餘時間回傳 (remain),信號安全

timespec 結構

struct timespec {
    time_t tv_sec;   // 秒
    long   tv_nsec;  // 奈秒 (0~999999999)
};

nanosleep 範例

void ns_sleep(long ns) {
    struct timespec req = { .tv_sec = ns / 1000000000, .tv_nsec = ns % 1000000000 };
    struct timespec rem;
    while (nanosleep(&req, &rem) == -1 && errno == EINTR) {
        req = rem;  // 被信號中斷,續睡剩餘時間
    }
}

4. 精度與時鐘源

  • 核心配置 CONFIG_HIGH_RES_TIMERS + 動態滴答 (NO_HZ) 可達奈秒級精度。
  • 硬體時鐘源 (TSC, HPET, ACPI PM) 影響實際精度,cat /sys/devices/system/clocksource/clocksource0/current_clocksource 查看。
  • 進程調度延遲 (CFS、即時優先級) 通常是誤差主因,非 API 本身。

5. 選擇建議

場景推薦 API
簡單微秒級延遲usleep() / select()
高精度週期性任務timer_create() + timer_settime() (POSIX 定時器)
事件驅動主迴圈select()/poll()/epoll() 超時
需被信號中斷並續睡nanosleep()
硬體即時控制考慮 SCHED_FIFO + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME)

結語

現代 Linux 應用開發中,nanosleep() 為首選高精度休眠 API,select() 適合事件迴圈整合,setitimer() 因資源限制與信號複雜度逐漸被 timerfd / POSIX 定時器取代。理解時鐘源、調度延遲與信號交互是實現精確定時的關鍵。

Copyright © Windows教程網 All Rights Reserved