C 言語で nanosleep 関数を使用する

胡金庫 2023年10月12日
  1. 関数 nanosleep を使って C 言語で高分解能タイマを使ってプログラムの実行を中断する
  2. C 言語で nanosleep 関数が正常に実行されたかどうかを調べる
C 言語で nanosleep 関数を使用する

この記事では、C 言語で nanosleep 関数を利用する方法をいくつか説明します。

関数 nanosleep を使って C 言語で高分解能タイマを使ってプログラムの実行を中断する

nanosleep は POSIX に準拠したシステムコールであり、プログラムの実行を一定時間中断するためのものです。他の関数も同様の処理を行う機能を提供しているが、sleep はそのうちの一つであり、呼び出し処理を中断するのに数秒かかる。sleep は低解像度の中断を提供すると言われています。これに対して、nanosleep では、ユーザがナノ秒単位の精度でスリープ期間を指定することができます。

関数 nanosleepstruct timespec オブジェクト型の 2つのアドレスを受け取ります。秒数を表す tv_sec とナノ秒数を表す tv_nsec です。最初の timespec 構造体は一時停止の期間を指定するために使われます。なお、tv_nsec の値は 0 から 999999999 の範囲内でなければならないことに注意してください。次の例では、10 回の繰り返しでループを実行し、5 サイクル目に nanosleep を呼び出してプロセスを中断しています。

#include <errno.h>
#include <stdio.h>
#include <stdlib.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 は与えられた期間だけプロセスを中断させるべきであるが、システム内にはそれを中断してエラーコードを返し、errnoEINTR に設定するよう強制するイベントが存在します。この場合、第 2 引数 timespec は、関数呼び出しがシグナルによって中断された残りの期間を格納するために使用されます。このオブジェクトはその後再び nanosleep を呼び出して、今度はスリープを終了させることができます。次の例では、複数のエラーコードをチェックし、対応するメッセージを表示し、必要に応じてコードの実行を処理する方法を示します。

#include <errno.h>
#include <stdio.h>
#include <stdlib.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
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook