在 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