在 C 語言中使用 nanosleep 函式

Jinku Hu 2023年1月30日 2021年2月28日
  1. 在 C 語言中使用 nanosleep 函式用高解析度定時器暫停程式執行
  2. 檢查 C 語言中的 nanosleep 函式是否執行成功
在 C 語言中使用 nanosleep 函式

本文將介紹幾種在 C 語言中使用 nanosleep 函式的方法。

在 C 語言中使用 nanosleep 函式用高解析度定時器暫停程式執行

nanosleep 是一個符合 POSIX 標準的系統呼叫,用於在給定的固定時間段內暫停程式的執行。其他函式也提供了做同樣操作的設施,sleep 是其中之一,它需要若干秒來暫停呼叫程序。sleep 可以說是提供了低解析度的暫停。而 nanosleep 則允許使用者以納秒的精度指定睡眠時間。

nanosleep 函式需要兩個型別為 struct timespec 物件的地址,這兩個地址都有兩個資料成員。tv_sec-代表秒數,tv_nsec-表示納秒數。第一個 timespec 結構用來指定懸浮的時間段。注意,tv_nsec 值必須在 0 到 999999999 的範圍內,否則,呼叫會失敗。在下面的例子中,我們執行一個有 10 次迭代的迴圈,並在第 5 個週期通過呼叫 nanosleep 暫停程序。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>

enum {SECS_TO_SLEEP = 3, NSEC_TO_SLEEP = 125};

int main() {
    struct timespec remaining, request = {SECS_TO_SLEEP, NSEC_TO_SLEEP};

    printf("Started loop..\n");
    for (int i = 0; i < 10; ++i) {
        printf("Iteration - %d\n", i);
        if (i == 4) {
            printf("Sleeping ....\n");
            nanosleep(&request, &remaining);
        }
    }

    exit(EXIT_SUCCESS);
}

輸出:

Started loop..
Iteration - 0
Iteration - 1
Iteration - 2
Iteration - 3
Iteration - 4
Sleeping ....
Iteration - 5
Iteration - 6
Iteration - 7
Iteration - 8
Iteration - 9

檢查 C 語言中的 nanosleep 函式是否執行成功

儘管 nanosleep 應該在給定的時間段內暫停程序,但系統中的一些事件會打斷它,迫使函式返回錯誤程式碼,並將 errno 設定為 EINTR。在這種情況下,第二個 timespec 引數用來儲存函式呼叫被訊號中斷的剩餘時間段。這個物件隨後可以再次呼叫 nanosleep,希望這次能完成睡眠。接下來的例子演示瞭如何檢查多個錯誤程式碼,列印相應的資訊,並根據需要處理程式碼執行。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>

enum {SECS_TO_SLEEP = 3, NSEC_TO_SLEEP = 125};

int main() {
    struct timespec remaining, request = {SECS_TO_SLEEP,  NSEC_TO_SLEEP};


    printf("Started loop..\n");
    for (int i = 0; i < 10; ++i) {
        printf("Iteration - %d\n", i);
        if (i == 4) {
            printf("Sleeping ....\n");

            errno = 0;
            if (nanosleep(&request, &remaining) == -1) {
                switch (errno) {
                    case EINTR:
                        printf("interrupted by a signal handler\n");
                        exit(EXIT_FAILURE);
                    case EINVAL:
                        printf("tv_nsec - not in range or tv_sec is negative\n");
                        exit(EXIT_FAILURE);
                    default:
                        perror("nanosleep");
                        exit(EXIT_FAILURE);
                }
            }
        }
    }

    exit(EXIT_SUCCESS);
}

輸出:

Started loop..
Iteration - 0
Iteration - 1
Iteration - 2
Iteration - 3
Iteration - 4
Sleeping ....
Iteration - 5
Iteration - 6
Iteration - 7
Iteration - 8
Iteration - 9
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn