Ich höre oft Treiber-Entwicklern zu, dass es gut sei, Kernel-Modus-Switches so weit wie möglich zu vermeiden. Ich konnte den genauen Grund nicht verstehen. Um mit meinem Verständnis zu beginnen, ist -
Unter diesen Operationen funktioniert syscall so ziemlich wie ein normaler Funktionsaufruf. Obwohl der Sender sich wie ein falsch vorhergesagter Zweig verhalten könnte, der zu ROB-Flush in der Prozessor-Pipeline führen könnte. Selbst das ist nicht wirklich schlecht, es ist wie jeder andere falsch vorhergesagte Zweig.
Ich habe ein paar Leute gehört, die auf Stack Overflow antworteten:
while(1);
garantiert keinen Kontextwechsel. Woher kommen die tatsächlichen syscall-Kosten?
Sie geben nicht an, für welches Betriebssystem Sie sich interessieren. Lass mich trotzdem eine Antwort versuchen.
Die CPU-Anweisungen syscall
und sysenter
sollten nicht mit dem Konzept eines Systemaufrufs und dessen Funktion verwechselt werden Darstellung in den jeweiligen Betriebssystemen.
Die beste Erklärung für den Unterschied in dem Overhead, der durch die jeweilige Anweisung entsteht, finden Sie in den Abschnitten Operation des Intel® 64 und IA-32 Architectures Developer's Manual Band 2A (für int
, siehe Seite 3-392) und Volume 2B (für sysenter
siehe Seite 4-463). Vergessen Sie auch nicht, währenddessen auf iretd
und sysexit
zu schauen.
Ein zufälliges Zählen des Pseudocodes für die Operationen ergibt:
int
sysenter
Hinweis: Obwohl die vorhandene Antwort insofern richtig ist, als sysenter
und syscall
keine Interrupts oder in irgendeiner Weise Interrupts sind, ältere Kernel in der Linux- und Windows-Welt verwendete Interrupts, um ihren Systemaufrufmechanismus zu implementieren . Unter Linux war dies int 0x80
und Windows int 0x2E
. Und folglich musste das IDT auf diesen Kernel-Versionen vorbereitet werden, um einen Interrupt-Handler für den jeweiligen Interrupt bereitzustellen. Bei neueren Systemen haben die Anweisungen sysenter
und syscall
die alten Möglichkeiten vollständig ersetzt. Mit sysenter
wird das MSR (maschinenspezifische Register) 0x176
mit der Adresse des Handlers für sysenter
initialisiert (siehe das unten verlinkte Lesematerial).
Ein Systemaufruf unter Windows führt genau wie unter Linux zum Wechsel in den Kernel-Modus. Der Scheduler von NT gibt keine Garantien über die Zeit, die ein Thread gewährt wird. Außerdem entfernt es Zeit von Threads und kann sogar verhungernde Threads enden. Im Allgemeinen kann man sagen, dass der Benutzermoduscode durch den Kernelmoduscode vorweggenommen werden kann (mit sehr wenigen sehr spezifischen Ausnahmen, die Sie sicherlich in der "erweiterten Treiberschreibklasse" erhalten werden). Das macht Sinn, wenn wir nur ein Beispiel betrachten. Benutzermoduscode kann ausgelagert werden - oder die Daten, auf die er zuzugreifen versucht. Nun hat die CPU nicht die geringste Ahnung, wie sie auf die Seiten in der Swap- / Paging-Datei zugreifen kann. Daher ist ein Zwischenschritt erforderlich. Und das ist auch der Grund, warum der Kernelmodus-Code dem Benutzermoduscode zuvorkommen muss. Es ist auch der Grund für einen der produktivsten Bug-Check-Codes in Windows und meist durch Treiber von Drittanbietern verursacht: IRQL_NOT_LESS_OR_EQUAL
. Es bedeutet, dass ein Treiber auf ausgelagerten Speicher zugegriffen hat, wenn es nicht möglich war, den Code, der diesen Speicher berührt, vorher zu löschen.
KiFastSystemCall
SYSENTER
/ SYSCALL
ist nicht ein Software-Interrupt; Der ganze Punkt dieser Anweisungen ist, einen Overhead zu vermeiden, der durch das Ausgeben von IRQ und das Aufrufen des Interrupt-Handlers verursacht wird.
Das Speichern von Registern auf der Stack-Kosten-Zeit ist ein Ort, von dem die Kosten des Systemprotokolls kommen.
Ein anderer Ort kommt von dem Kernel-Modus-Schalter selbst. Es müssen die Segmentregister geändert werden - CS, DS, ES, FS, GS, alle müssen geändert werden (es ist weniger kostenaufwendig auf x86-64, da die Segmentierung meist ungenutzt ist, aber man muss immer noch weit zum Kernel-Code springen) und ändert auch CPU-Ring der Ausführung.
Zum Schluss: Funktionsaufruf ist (auf modernen Systemen, wo die Segmentierung nicht verwendet wird) in der Nähe des Anrufs, während der Syscall Fernruf und Ringwechsel beinhaltet.
Tags und Links x86 kernel performance system-calls