Windowsでは、次のように呼び出すことができます。
_time32(__time32_t); // to get 32-bit time_t
_time64(__time64_t); // to get 64-bit time_t
(32ビットプログラムと64ビットプログラムの両方)
Linux(GCCでコンパイル)でこれを行う方法はありますか?
どうやら、それは不可能です。手始めに、Linuxにはtime()
関数が1つだけあり、time32()
またはtime64()
はありません。
しばらく検索したところ、libcのせいではないことがわかりましたが、原因は実際にはカーネルです。
Libcが現在の時刻をフェッチするには、次のシステムコールを実行する必要があります。 ( ソース )
_time_t time (t) time_t *t;
{
// ...
INTERNAL_SYSCALL_DECL (err);
time_t res = INTERNAL_SYSCALL (time, err, 1, NULL);
// ...
return res;
}
_
システムコールは次のように定義されます。 ( ソース )
_SYSCALL_DEFINE1(time, time_t __user *, tloc)
{
time_t i = get_seconds();
// ...
return i;
}
_
関数get_seconds()
は、次のように_unsigned long
_を返します。 ( ソース )
_unsigned long get_seconds(void)
{
struct timekeeper *tk = &timekeeper;
return tk->xtime_sec;
}
_
そして、_timekeeper.xtime_sec
_は実際には64ビットです: ( ソース )
_struct timekeeper {
// ...
/* Current CLOCK_REALTIME time in seconds */
u64 xtime_sec;
// ...
}
_
さて、あなたがあなたのCを知っているなら、あなたは_unsigned long
_のサイズが実際には実装に依存していることを知っています。ここにある私の64ビットマシンでは、64ビットです。しかし、ここの私の32ビットマシンでは、32ビットです。 おそらく一部の32ビット実装では64ビットである可能性がありますが、保証はありません。
一方、_u64
_は常に64ビットであるため、カーネルは基本的に64ビット型で時間を追跡します。その後、64ビット長が保証されていない_unsigned long
_としてこれを返す理由は私にはわかりません。
結局、libcが_time_t
_に64ビット値を保持するように強制したとしても、それは何も変更しません。
アプリケーションをカーネルに深く結び付けることもできますが、それだけの価値はないと思います。
time64()/time32()
関数は標準ライブラリに含まれていません。
標準ヘッダーでは、time32_t/time64_t
定義は考慮されていません。
time_t
はtime.h
にtypedef __time_t time_t
として定義されています。
再定義の長いチェーンに続いて、__time_t
が32ビットマシンでは32ビット、64ビットマシンでは64ビットとして定義されていることがわかります。
上記の多くの回答は、これは不可能であると述べていますが、それは完全に間違っています。当時は不可能でしたが、人々は何年もの間 それを修正することについて話していました でした。最後に、32ビットプラットフォームでの64ビット時間のサポートは Linux 5.1カーネルに導入されました 新しい _*time64
_ syscalls が追加されました。 この表 を見てください。これらのシステムコールは64ビットプラットフォームでは使用できないことがわかります。 32ビットシステムのコードを記述している場合は、_clock_gettime64
_を直接(インラインアセンブリまたはCから syscall()
を使用して)呼び出して、現在の時刻を取得できます。
しかしその後、あなたは完全にあなた自身になります。完全なuserspaceサポートが必要な場合は、Linux5.6以降とmusl1.2 +またはglibc2.32 +を使用している必要があります。コードを再構築するだけで、_time_t
_は64ビット長になります
すべてのユーザースペースは、64ビットの_
time_t
_でコンパイルする必要があります。これは、今後のmusl-1.2およびglibc-2.32リリースでサポートされ、linux-5.6以降のカーネルヘッダーがインストールされます。システムコールインターフェイスを直接使用するアプリケーションは、既存のシステムコールの代わりにlinux-5.1で追加されたtime64syscallを使用するように移植する必要があります。これは、
futex()
とseccomp()
のほとんどのユーザー、およびlibcに基づかない独自のランタイム環境を持つプログラミング言語に影響を与えます。
詳細については
あなたが本当にこれを必要とするならば、なぜあなた自身を転がしてみませんか?
_typedef int32_t my_time32;
typedef int64_t my_time64;
my_time32 get_mytime32() {
if (sizeof(time_t) == sizeof(my_time32))
return time(NULL);
else {
/* Check for overflow etc. here... */
return (my_time32)(time(NULL));
}
}
_
同様にget_mytime64()
についても同様です。
オーバーフローを気にしない場合は、Cの暗黙的な数値変換のおかげで、単純なreturn time(NULL);
が両方の関数で機能します。
このライブラリを使用してください: https://github.com/evalEmpire/y2038
このプロジェクトの目標は、POSIX time.hのドロップイン置換を提供することです。これは、32ビットのtime_tを持ちながら、2038バグの影響を受けていないマシンで動作します。これにより、Cプログラマーは、ソフトウェアを新しいインターフェイスに書き直すことなく、2038年に安全になります。これは、システムタイムゾーンデータベースを使用しながら行います。