アクセス可能な Raspberry Pi および Ubuntu 16.04 x86_64 マシンで、次を実行します。
# date -s @0
返品
date: cannot set date: Invalid argument
thu 1 jan 1970 01:00:00 CET
私は知りたいです:
- 不可能の理由は何か、
- システム時間をEpochにリセットするプログラムはありますか?
答え1
以前のシステムでは「無効な引数」を正確に再現できませんでしたが、
# strace date -s '@-1'
…
clock_settime(CLOCK_REALTIME, {4294967295, 0}) = -1 EINVAL (Invalid argument)
settimeofday({4294967295, 0}, NULL) = -1 EINVAL (Invalid argument)
write(2, "date: ", 6date: ) = 6
write(2, "cannot set date", 15cannot set date) = 15
write(2, ": Invalid argument", 18: Invalid argument) = 18
write(2, "\n", 1
(date
実際にまだ設定されていない場合でも、設定したい日付が表示されます。)
一般英語では、date
カーネルを呼び出して日付を新起源の1秒前に設定し、カーネルは提案された日付が無効であることを伝えます。
これで、上記のトレースでは、秒が-1の代わりに4294967295であることがわかります。数字は2^32-1で、32ビットシステムで実行されています。これは実際にいいえ問題の原因:strace
値に署名する必要があるかどうかわからないという点で、ディスプレイの問題です。実際、秒数は符号付き整数型ですtime_t
。 LinuxのGlibc 2.23は、as、as、asでtime_t
64ビット符号付き型を定義します。カーネル側で4.4以降、呼び出しパラメータタイプの定義は次のとおりです。__time_t
/usr/include/time.h
__time_t
__TIME_T_TYPE
/usr/include/bits/types.h
__TIME_T_TYPE
__SYSCALL_SLONG_TYPE
__SQUAD_TYPE
/usr/include/bits/typesizes.h
__SQUAD_TYPE
/usr/include/bits/types.h
settimeofday
struct timespec
秒はどこにありますか?__kernel_time_t
64ビットシステムの符号付き64ビットタイプ。time64_t
これは32ビットシステムの符号付き64ビットタイプです。したがって、カーネルは-1を大きな正の数ではなく-1として扱います。
以前の時代に戻ることができなかった理由は、Linuxカーネルがこれを明示的に拒否するためです。これsettimeofday
システムコールif が EINVAL("無効なパラメータ") を返す場合timeval_valid
与えられた時間的構造を拒否し、この機能負の秒は拒否されます。
カーネルバージョンごとにコード構成が異なりますが、動作が変わらないと思います。
正確にゼロの時間を拒否する理由はなく、テストしたVMで動作します。
おそらく、この完全性チェックの理由は、エポック以降の時間を符号なし整数として格納するコードがあり、エポック前の日付を処理できないためです。一部のコードはゼロを「不明な日付」と解釈する可能性があるため、ゼロを拒否するのは合理的ですが、Linuxは実際にはそうしません。
時代以前の時代は、確実に再現および操作することができます。多くのソフトウェアでは、過去のイベント時間を追跡する必要があります。ほとんどすべてのオペレーティングシステムで使用されるタイムゾーンデータベースには、タイムゾーンがコード化された時期(鉄道が使用され始めた時期)までさかのぼる履歴データが含まれています。しかし、Linuxコンピュータには不明です。現在の時は1970年以前だった。
答え2
これは、現在のタイムゾーンのエポックの概念が(UTC)Unixエポックより前の場合に発生する可能性があります。そのような時代は代表できません。