ソフトな忘却力(23) time_t型、64bit OS上なら64bitになっていたのね

Joseph Halfmoon

別件でdateコマンドを使って思い出したのが UNIX時間であります。Linuxでも使用の「伝統」です。そういえば昔は32ビットであったので2038年問題ってのが有った筈。手元のLinux機、ラズパイ4はようやく64ビットOSに切り替えましたが、ラズパイ3は32ビットOSのままです。time_t型の件、調べてみました。

年寄りの忘却力は著しいものがありますが、昔のことは良く覚えておりますぞ。Unix時間とは、

UTCの1970年1月1日午前0時0分0秒を Unix Epochとして、そこからの経過秒数(符号付き整数であらわす)

であります。この1970年初からの経過秒数は、Unixに影響をうけた、勿論、世に蔓延るLinuxを含む、あまねくほとんどのコンピュータシステム上で使用可能。プログラム書くときの礎(言い過ぎでないかい?)かと思います。閏秒の扱いとかいろいろあるみたいですが、その辺はパスさせていただきます。

この経過秒数を表す数値の型として

time_t

が定義されているのでありますな。しかし、旧来のシステムでは、実際はlong int型であります。longといいつつ、当時はintが16ビットであったりしたので、32ビットです。そして符号付きなので実質31ビットしか表現できませぬ。よって恐ろしいことに

2038年1月19日午前3時14分07秒

になるとラップアラウンドする(閏秒分前後にズレるかも)、というのが2038年問題でした。

「でした」などと書いてますが、今も「現役の問題」であります。UNIX時刻がオーバーフローしたらどんな恐ろしいことになるか予想も付きません。しかし、あまり気にしている人は多くない気がします(個人の感想です。)

振り返ってみれば、2000年問題のときは大騒ぎでしたですな。私なんぞは2000年問題にあんまり関係ない職種だと自覚していたのです。しかし当時勤めていた会社は立派なことに、リスク管理のため管理職に「その期間」衛星携帯電話を持たせてました。何かあれば連絡するぞという決意です。ただねえ、当時出始めだった衛星携帯電話、デカくて重いだけではなかったです。太平洋の真ん中でも南極でも通話可能、といいつつ、普通の木造家屋の屋内では受信不可と。結局、正月休みの最中、常に窓際の空の見える場所に陣取り、窓に電話を立てかけておりました。ともあれ2000年問題のときは、相当前から対処に駆り出された人々は多く、皆さまの努力のお陰で大きな問題は起きなかったような記憶です(怪しいですが。)

ラズパイ上でtime_tのサイズの確認

結論から言えば、32bit OSでも64bit OSでも

    • time_t は、結局 long int
    • しかし __WORDISZE が 64ならば long int は64ビット符号付き、32ならばlong int は32ビット符号付き
    • よって32 bit OS上では32ビット、64 bit OS上では64ビット

です。

実機上で上記を確かめるために以下のソースを作成してみました。

#include <stdio.h>
#include <stdlib.h>
#include "sys/time.h"

int main(int argc, char *argv[]) {
    struct timeval tv;
    int stat;
    printf("sizeof time_t: %d\n", sizeof tv.tv_sec);
    if (!gettimeofday(&tv, NULL)) {
        printf("  tv_sec : %d\n", tv.tv_sec);
        printf("  tv_usec: %d\n", tv.tv_usec);
    } else {
        printf("  ERROR: gettimeofday");
    };
    exit(0);
}
ビルドして実行

Raspberry pi OS 32bit / 64bit とも上記のソースのコンパイルのためのコマンドラインは同じです(gccのバージョンは違いますが。)

$ gcc -g -O0 -o trainTime trainTime.c

さて、32bit OS(ラズパイ3使用)上での実行結果が以下に。uname -a で “armv7l”の文字が見えます。32bitの命令セットであることが分かります。

そこでの time_tのサイズは4バイトとな。

Pi3

続いて、64bit OS(ラズパイ4使用)上での実行結果が以下に。uname -a で “aarch64″の文字が見えます。64bitの命令セットです。

そこでの time_tのサイズは8バイトとな。Pi4

どちらも、tv_secとして16億6028万七千台の数字が読めております。これこそUNIX時間ですな。これが後16年ほどたつと上記の32ビットOSでは、ラップアラウンドして負の数に飛び、下記の64ビットOSでは多分問題ない、と。

でもまあ、そこまで32ビットOSを使い続けているケースは「稀」な気がします。でも必ずきっと「少し」「隠れたところに」残っていると確信してます。いままでだってそうだったし。。。微妙に怖い。でも私はそこまで生きているかどうかも正直怪しい。知らんけど。

ソフトな忘却力(22) シグナル、無視するにはsigprocmask()使う方が良いのね へ戻る

ソフトな忘却力(24) 久しぶりのgprof、簡単なところから思い出す へ進む