在 C 語言開發中,讓程式暫停執行一段指定時間是常見需求。然而,C 標準庫並未提供統一的睡眠函數,導致 Windows 與類 Unix 系統(Linux、macOS)需使用不同的 API。本文將深入探討 Sleep()(Windows)與 sleep()、usleep()、nanosleep()(POSIX)的用法、差異,並提供跨平台封裝建議。
在 Windows 系統上,需包含 <windows.h> 標頭檔,使用 Sleep() 函數,其參數單位為毫秒。
#include <windows.h>
#include <stdio.h>
int main() {
printf("程式開始執行...\n");
Sleep(1000); // 暫停 1000 毫秒(1 秒)
printf("1 秒後繼續執行。\n");
return 0;
}
注意事項:
Sleep() 的精度受系統排程器影響,通常約 10-15 毫秒。timeBeginPeriod / timeEndPeriod,但會增加系統電力消耗。類 Unix 系統提供三種主要睡眠函數,精度由低到高:
| 函數 | 標頭檔 | 單位 | 備註 |
|---|---|---|---|
sleep() | <unistd.h> | 秒 | 若被訊號中斷,會提前返回剩餘秒數 |
usleep() | <unistd.h> | 微秒 | 已標記為過時,建議改用 nanosleep() |
nanosleep() | <time.h> | 奈秒 | 高精度,支援中斷後續眠剩餘時間 |
#include <time.h>
#include <stdio.h>
#include <errno.h>
void msleep(long milliseconds) {
struct timespec req, rem;
req.tv_sec = milliseconds / 1000;
req.tv_nsec = (milliseconds % 1000) * 1000000L;
while (nanosleep(&req, &rem) == -1 && errno == EINTR) {
req = rem; // 被訊號中斷,繼續睡剩餘時間
}
}
int main() {
printf "開始...\n";
msleep(500); // 500 毫秒
printf "0.5 秒後繼續。\n";
return 0;
}
為了編寫可移植程式碼,建議使用巨集或內聯函數封裝平台差異:
#ifdef _WIN32
#include <windows.h>
#define MSLEEP(ms) Sleep(ms)
#else
#include <time.h>
#include <errno.h>
static inline void msleep(long ms) {
struct timespec req = { ms / 1000, (ms % 1000) * 1000000L }, rem;
while (nanosleep(&req, &rem) == -1 && errno == EINTR) req = rem;
}
#define MSLEEP(ms) msleep(ms)
#endif
// 使用範例
MSLEEP(2000); // 跨平台暫停 2 秒
while(clock() < target); 這類忙碌等待,會佔滿 CPU 核心。sleep() 若被訊號中斷會返回剩餘秒數,務必檢查返回值並重新睡眠。pthread_cond_timedwait 或 Windows 事件物件。掌握 Sleep 與 sleep 族函數的平台差異,並以跨平台封裝隔離細節,是撰寫可移植 C 程式的關鍵步驟。實務上,根據精度需求選擇 nanosleep()(高精度)或 sleep()(簡單秒級延遲),並妥善處理訊號中斷,即可穩健實現程式暫停功能。