Ich habe ein sehr einfaches Programm mit den Aufrufen time()
geschrieben, um die Verwendung von strace
zu verdeutlichen, aber ich habe ein Problem; Der Aufruf time()
scheint keinen Syscall zu erzeugen!
Ich bin dann in die time()
Funktion in GDB getreten und jetzt bin ich noch verwirrter als je zuvor. Von der Demontage der Funktion time()
:
Wie bekommt diese Funktion tatsächlich die aktuelle Uhrzeit, wenn sie den Kernel nicht aufruft? Sein Ablauf ist:
(0x7ffff7ffad94 + 0xffffffffffffd30d)
( 0x7ffff7ff80a8
) und lege ihn in rax (um zurückgegeben zu werden) Dies macht Sinn mit der Funktionalität von time()
; Wenn das Argument null ist, gibt es nur den Wert zurück, wenn nicht, wird es auch in das Argument geschrieben. Die Frage, die ich habe, ist, wo bekommt es den Zeitwert? Was ist so zauberhaft an der Adresse 0x7ffff7ff80a8
und wie geht das ohne einen Systemaufruf?
Ich benutze GCC 6.3.0 und Ubuntu GLIBC 2.24-9ubuntu2.2.
Lesen Sie time (7) . Wahrscheinlich verwendet Ihr Anruf bei time (2) das vdso(7) (vielleicht über clock_gettime (2) oder via __vdso_time
). Wenn vdso (7) verwendet wird,
Bei der Verfolgung von Systemaufrufen mit strace (1) , Symbolen (Systemaufrufen) die vom vDSO exportiert werden, wird nicht in der Ablaufverfolgungsausgabe angezeigt.
Details könnten kernel- und libc-spezifisch (und natürlich architekturspezifisch) sein.
Bei ähnlichen vDSO Gründen zeigt strace date
keine zeitbezogenen Systemaufrufe.
Und vDSO ist eine wirklich praktische Funktion. Dank dieser Funktion werden Timing-Aufrufe (zB clock_gettime (2) ...) wirklich ausgeführt schnell (ungefähr 40 Nanosekunden auf meinem i5-4690S). AFAIU, kein Kontextwechsel (oder Benutzer zum Kernel Modus Übergang) passiert.
Ihr 0x7ffff7ff80a8
befindet sich wahrscheinlich im vDSO (und der Kernel stellt sicher, dass es die aktuelle Zeit enthält). Sie können dies überprüfen, indem Sie proc (5) verwenden (zB lesen und /proc/self/maps
in Ihrem Programm anzeigen) oder vielleicht ldd (1) .