のぴぴのメモ

自分用のLinuxとかの技術メモ

Linuxのclock_gettime()でナノ秒の時刻を取得し表示する

1.はじめに

clock_gettime()で時刻を取得し時刻をナノ秒で表示するサンプルです。時刻取得といえばgettimeofday()ですが、POSIXではgettimeofdayは廃止予定で、clock_gettime()の利用を推奨しているので、こちらを利用しています。

2.コードと実行例

(1)コード

#include <stdio.h>
#include <time.h>
int main(){
	struct timespec ts;
	struct tm tm;
	// 時刻の取得
	clock_gettime(CLOCK_REALTIME, &ts);  //時刻の取得
	localtime_r( &ts.tv_sec, &tm);       //取得時刻をローカル時間に変換
	// 出力
	printf("tv_sec=%ld  tv_nsec=%ld\n",ts.tv_sec,ts.tv_nsec);
	printf("%d/%02d/%02d %02d:%02d:%02d.%09ld\n",
		tm.tm_year+1900,
		tm.tm_mon+1,
		tm.tm_mday,
		tm.tm_hour,
		tm.tm_min,
		tm.tm_sec,
		ts.tv_nsec);
	return(0);
}

(2)実行例

$ gcc sample.c
 $./a.out 
tv_sec=1508516823  tv_nsec=736416218
2017/10/21 01:27:03.736416218

RHEL7でのビルド&実行例です。version 2.17より前のgccの場合はリンク時に”-lrt”オプションを付与する必要があります。(多分、RHEL5以前)

3.説明

(1)clock_gettime(CLOCK_REALTIME, &ts)

時刻を取得します。最初の引数は取得する時刻の種類を指定しており、"CLOCK_REALTIME"はシステム全体で一意な精度の高い実時間情報を取得します。取得した情報は、2つ目の引数のtimespec構造体に格納されます。

struct timespec {
	time_t   tv_sec;       ==> 1970年1月1日からの秒数が格納されます。
	long     tv_nsec;      ==> 秒未満の時刻(ナノ秒)で格納されます。
};

(2)localtime_r( &ts.tv_sec, &tm)

取得した時刻のうち、tv_sec(1970年1月1日からの秒数)を年/月/日/時/分/秒に変換し、tm構造体に格納します。
localtime_r()は、localtime()と同じ処理になりますが、localtime()はスレッドセーフでなく、localtime_r()はスレッドセーフな実装になります。スレッドセーフでないlocaltime()はマルチスレッド環境で利用すると想定外の挙動を起こす可能性があるため、今回のサンプルではマルチスレッドでも使えるように、スレッドセーフなlocaltime_r()を利用しています。

(3)printfで出力

localtime_rで変換した時刻情報を、printf()で出力します。秒未満は、timespecのtv_nsecに格納されているので、tv_nsecを使って秒の小数点以下の値を出力しています。


f:id:nopipi:20171028095337p:plain
clock_gettime()で時刻取得して変換出力する概要