ablog

不器用で落着きのない技術者のメモ

2038年問題

glibc で time_t は long int で、gcc で 32bit モードでコンパイルすると 32bit、64bit モードだと 64bit になる(ワードサイズになる)ということぽい。

LONG_TYPE_SIZE
A C expression for the size in bits of the type long on the target machine. If you don't define this, the default is one word.

GNU Compiler Collection (GCC) Internals

参考

Linuxシステムプログラミング

Linuxシステムプログラミング

P.319

10.1.1 初期の時刻表現
もっとも単純なデータ構造は、で定義されている、time_t です。time_t の目的は型の抽象化にありますが、Linux を含むほとんどの Unix システムではC言語の単なる long として typedef しています。

typedef long time_t

time_t は epoch からの経過秒数を表現します。「それじゃすぐにオーバフローするじゃないか!」と言う反応もよくありますが、実際には思ったよりも長持ちします。しかし、現在稼働している多くの Unix システムがオーバフローすることは間違いありません。long 型が32ビットの場合に、time_t が表現可能な値は epoch から2,147,483,647 秒後までです。このことはY2K問題と全く同じ騒動が2038年に湧き起こることを意味します。しかし、2038年1月18日(月)22:14:07*1までには、ほとんどのシステムおよびソフトウェアが64ビット化されていることでしょう。

P.320

10.1.2 現状の時刻表現(マイクロ秒)
time_t にはもう一つ問題があります。秒単位では分解能が低すぎ、1秒間に発生するイベント数が非常に多くなる点です。このため、time_t を拡張し、マイクロ秒の分解能を加えた timeval 構造体も導入され、 で次のように定義されています。

#include <sys/time.h>

struct timeval {
 time_t tv_sec; /* seconds */ 秒
 suseseconds_t tv_usec; /* microseconds */ マイクロ秒
}

tv_sec は秒を、tv_usec はマイクロ秒をそれぞれ表します。suseconds_t が分かりにくいかもしれませんが、通常は整数型の typedef です。

Linuxプログラミングインタフェース

Linuxプログラミングインタフェース

P.193

10.1 カレンダ時間
32ビットのLinuxシステムではtime_t(符号付き整数型)は1901年12月13日20:45:52から2038年1月19日03:14:07までを表現できます(SUSv3では値が負の time_t については未定義としています)。

P.195

本質的に同じシステムコールである、time()とgettimeofday()の2つが存在する理由も歴史的なものです。初期のUNIXではtime()のみを実装しており、4.2BSDが精度を求め、gettimeofday()システムコールを追加しました。現在ではtime()をシステムコールとして実装するのは冗長と言えるでしょう。ライブラリ関数として実装し、内部でgettimeofday()を実行すれば済むことです。

*1:米国東部時間