web-dev-qa-db-ja.com

Linuxユーティリティがシステムコールを使用して現在の時刻を取得しないのはなぜですか?

ゲストVMが「想定どおりに」kvm-clockドライバーを使用していない理由を本当に理解しようとしています。彼らはRHEL7.2、glibc-2.17、kern3.10.0を実行しています。 datePerl -e 'print time'などのプログラムは現在の時刻を取得しますが、システムコールを行わずに取得します。これはstraceとltraceで確認され、gdbを使用して、syscallをバイパスし、代わりにrtdscpと呼ばれるいくつかの命令を実行したアセンブリを介してトレースすることで確認されます。

これはglibcの作者による最適化の試みですか?これを無効にして、glibc呼び出しにシステムコールを強制する方法はありますか(LD_PRELOADハックを除く)?

[〜#〜]更新[〜#〜]2016-10-14:

最新の POSIXドラフト を確認した後、答えの一部は明らかです:CPUからクロックを要求する方法がありますが、GNU glibcがこの実装を誤って強制しています回避策は、システムコールを直接呼び出すことです。(Booooh)

_POSIX_CPUTIMEが定義されている場合、実装は、特定のプロセスのCPU時間クロックを表すclock_getcpuclockid()を呼び出すことによって取得されたクロックID値をサポートする必要があります。実装は、clock _()またはtimer _()関数のいずれかを呼び出すときの呼び出しプロセスのCPU時間クロックを表す特別なclockid_t値CLOCK_PROCESS_CPUTIME_IDもサポートする必要があります。

ユーザーができることを考えると、clock_idCLOCK_REALTIMEに設定されている場合、システムコールを使用する必要があるという考えに対して実際の引数はありますか?

3
Otheus

Syscallが発生していない理由は、一部のLinuxシステムコール(特にgettimeofday(2)time(2)などの時間に関連するもの)が- vDSO 、いくつかのシステムコールのいくらか最適化された実装が含まれています:

「vDSO」(仮想動的共有オブジェクト)は、カーネルがすべてのユーザー空間アプリケーションのアドレス空間に自動的にマップする小さな共有ライブラリです。

カーネルが提供するいくつかのシステムコールでは、ユーザースペースコードが頻繁に使用され、そのような呼び出しが全体的なパフォーマンスを支配する可能性があります。これは、呼び出しの頻度と、ユーザー空間を終了してカーネルに入ることに起因するコンテキスト切り替えオーバーヘッドの両方が原因です。

現在、マニュアルには、プロセスが直接アクセスできるように、必要な情報がメモリに配置されるだけであると記載されています(結局のところ、現在の時刻はそれほど秘密ではありません)。正確な実装についてはわかりませんが、CPUのタイムスタンプカウンターの役割についてしか推測できませんでした。

したがって、最適化を行うのは実際にはglibcではなく、カーネルです。 カーネルコマンドラインvdso=0を設定することで無効にでき、コンパイルできるはずです。ただし、glibc側でそれを無効にできるかどうかはわかりません(少なくともライブラリにパッチを適用しない限り)。

これには他にもたくさんの情報と情報源があります SEに関する質問


あなたは質問で言った:

最新のPOSIXドラフトを確認した後、答えの一部は明らかです。CPUからクロックを要求する方法はありますが、GNU glibcはユーザーにこの実装を誤って強制しました。

これはかなり大胆な発言だと思います。少なくともユーザーの不利益を除いて、ユーザーに「誤って強制」したという証拠は見当たりません。 vDSOの実装は、現在のシステムで実行されているほぼすべてのLinuxプロセスで使用されています。つまり、正しく機能しなかった場合、非常に大きな苦情がすでに聞こえていたはずです。また、あなたは受け取った時間が正しいとあなた自身に言いました。

clock_gettimeマニュアルからの引用は、呼び出しが clock_getcpuclockid によって返されるクロックIDをサポートする必要があることのみを示しているようであり、CLOCK_REALTIMEまたは gettimeofday

11
ilkkachu