Heim > Artikel > Backend-Entwicklung > Was ist der Zweck des Systemaufrufs?
Der Zweck des Systemaufrufs besteht darin, Systemdienste anzufordern. Das Betriebssystem erlaubt Benutzern nicht, verschiedene Hardwareressourcen direkt zu bedienen, sodass Benutzerprogramme den Kernel nur über Systemaufrufe für seine Dienste anfordern und verschiedene Ressourcen indirekt nutzen können.
Die vom Betriebssystem bereitgestellten Funktionen werden in der Regel nicht von der Anwendung selbst implementiert. Um beispielsweise Dateien zu bearbeiten, muss die Anwendung Systemaufrufe durchführen, da nur das Betriebssystem die Berechtigung hat, Peripheriegeräte direkt zu verwalten. Ein weiteres Beispiel ist der synchrone gegenseitige Ausschlussvorgang zwischen Prozessen oder Threads, der ebenfalls vom Betriebssystem ausgeführt werden muss, um Kernelvariablen aufrechtzuerhalten.
Sehen Sie sich ein komplettes Computersystem von unten nach oben an: physische Hardware –>OS-Kernel –>OS-Dienst –>Anwendung. Der Betriebssystemkern spielt hier eine Schlüsselrolle bei der „Verbindung des Vorhergehenden mit dem Nächsten“, der Verwaltung der physischen Hardware nach unten und der Bereitstellung von Schnittstellen für Betriebssystemdienste und Anwendungen nach oben. Die Schnittstelle ist hier der Systemaufruf.
Der Anwendungsprozess läuft normalerweise im Benutzermodus. Wenn er einen Systemaufruf aufruft, wechselt der Prozess in den Kernelmodus und führt den Code innerhalb des Kernels aus, sodass er die Berechtigung hat, privilegierte Anweisungen auszuführen und bestimmte Funktionen auszuführen. Mit anderen Worten: Systemaufrufe sind der Eingang für Anwendungen, um aktiv in den Betriebssystemkernel einzudringen.
Wie der Name schon sagt, handelt es sich um Funktionen In Bibliotheken werden einige häufig verwendete Funktionen kompiliert und in einer Datei abgelegt, damit andere sie verwenden können. Wenn andere es verwenden, fügen Sie einfach den Dateinamen mit #include hinzu, normalerweise in der lib-Datei.
Bibliotheksfunktionen werden hauptsächlich von zwei Parteien bereitgestellt: Eine wird vom Betriebssystem bereitgestellt, die andere wird von einem Dritten bereitgestellt.
Diese vom System bereitgestellten Funktionen kapseln oder kombinieren Systemaufrufe, um mehr Funktionen zu erreichen. Solche Bibliotheksfunktionen können einige Vorgänge implementieren, die für den Kernel komplexer sind. Beispielsweise kann die Lesefunktion Dateien basierend auf Parametern direkt lesen, aber die dahinter verborgenen Dateien, z. B. welche Spur, welcher Sektor und welcher Speicher darin geladen werden, sind Probleme, über die sich Programmierer keine Gedanken machen müssen. Zu diesen Vorgängen gehören auch Systemaufrufe. Beispielsweise ruft die Systemfunktion write () den gleichnamigen Systemaufruf auf, um den Schreibvorgang abzuschließen.
Für Bibliotheken von Drittanbietern sind sie tatsächlich mit Systembibliotheken identisch, mit der Ausnahme, dass sie weniger wahrscheinlich Systemaufrufe direkt verwenden, sondern über die vom System bereitgestellte API-Schnittstelle implementiert werden . Beispielsweise ruft printf tatsächlich die Systemfunktion write() auf. Die meisten Bibliotheksfunktionen von Drittanbietern sind Kapselungen von Systemfunktionen.
Die Verbindung zwischen Systemaufrufen und Bibliotheksfunktionen:
Tatsächlich ist das, was Systemaufrufe den Benutzern bieten, direkt Was reine erweiterte Dienste betrifft: Wenn wir benutzerfreundlicher sein und Funktionen haben möchten, die für bestimmte Situationen besser geeignet sind, müssen wir von den Benutzern selbst definiert werden, sodass Bibliotheksfunktionen abgeleitet werden, die einige Systemaufrufe umschließen. Wenn wir beispielsweise einen Satz in der Sprache C drucken möchten und die Bibliotheksfunktion printf nicht verwenden, müssen wir sie selbst implementieren und einige Systemfunktionen wie putc () und write () aufrufen. Es scheint problematischer zu sein, daher dienen Systemaufrufe der Benutzerfreundlichkeit der Betriebssystemschnittstelle, während Bibliotheksfunktionen der Benutzerfreundlichkeit bei der Programmierung dienen.
Unter dem Linux-Betriebssystem verwendet beispielsweise die C-Sprachbibliotheksfunktion printf tatsächlich den Schreibsystemaufruf, während die Bibliotheksfunktion strcpy (String Copy) keinen Systemaufruf verwendet. Darüber hinaus ist die Systemaufrufschnittstelle eines Systems normalerweise der kleinste Satz, der alle erforderlichen Funktionen ausführen kann. Es können mehrere Bibliotheksfunktionen vorhanden sein, die denselben Systemaufruf kapseln. Unter Linux werden beispielsweise die drei Bibliotheksfunktionen malloc, calloc und free durch den Aufruf des brk-Systemaufrufs vervollständigt.
Die Beziehung zwischen Anwendungen, Bibliotheksfunktionen und Systemaufrufen ist in der folgenden Abbildung dargestellt:
Der Unterschied zwischen Systemaufrufen und Bibliotheksfunktionen:
Bibliotheksfunktionsaufrufe sind Teil der Sprache oder Anwendung, während Systemaufrufe Teil des Betriebssystems sind.
Systemaufruf ist die Schnittstelle für Anwendungen zur Interaktion mit dem Kernel. Bei der Langzeitprogrammierung hat man herausgefunden, dass die Verwendung von Systemfunktionen einen großen Nachteil hat, nämlich die Portabilität des Programms. Beispielsweise unterscheiden sich die von Linux bereitgestellten Systemaufruffunktionen von denen von Windows.
Bibliotheksfunktionsaufrufe sind auf die Anwendungsentwicklung ausgerichtet und entsprechen Anwendungs-APIs. Es gibt viele Gründe für die Übernahme dieses Ansatzes:
2. Der Kernelmodus und der Benutzermodus der CPU
Normalerweise verfügt der Prozessor über zwei Modi: „Benutzermodus“ und „Kernelmodus“. Ein Tag-Bit wird verwendet, um zu identifizieren, in welchem Modus er sich gerade befindet. Der Kernelmodus kann alle Anweisungen ausführen, einschließlich privilegierter Anweisungen (hauptsächlich einige Hardwareverwaltungsanweisungen, z. B. Anweisungen, die den Inhalt des Basisadressregisters ändern), während der Benutzermodus keine privilegierten Anweisungen ausführen kann. Dieses Design dient hauptsächlich Sicherheitsproblemen, d. h. das Betriebssystem ist für die Verwaltung der Hardware verantwortlich, um Hardwareprobleme zu vermeiden, die durch falsches Design von Anwendungen der oberen Schicht verursacht werden.
Da nur das Betriebssystem die Hardware direkt bedienen kann, muss das Betriebssystem Schnittstellen bereitstellen, um Anwendungen Zugriff auf Hardwarefunktionen zu ermöglichen. Diese Schnittstellen werden als Systemaufrufe bezeichnet.
Wenn das Betriebssystem die Systemaufrufanforderung empfängt, wechselt der Prozessor in den Kernelmodus, um nach der Verarbeitung des Systemaufrufinhalts Anweisungen wie E/A-Vorgänge auszuführen und den Inhalt des Basisadressregisters zu ändern , die Operation Das System kehrt den Prozessor in den Benutzermodus zurück, um Benutzercode auszuführen.
Entspricht dem Kernelmodus und dem Benutzermodus der CPU. Der Betriebszustand des Prozesses ist in den Pipe-Modus (Kernmodus) und den Augenmodus (Benutzermodus) unterteilt. Einzelheiten finden Sie im Artikel: Betriebssystem – Benutzermodus und Kernelmodus
Interrupt (Interrupt) Dies bedeutet normalerweise, dass ein ausstehendes Ereignis innerhalb oder außerhalb der CPU auftritt, sodass die CPU die Ausführungsreihenfolge der aktuellen Anweisungen ändern muss, um solche Ereignisse zu verarbeiten. Bevor wir die Beziehung zwischen Interrupts und Systemaufrufen vorstellen, klassifizieren wir zunächst Interrupts.
Interrupts können grob in zwei Kategorien unterteilt werden:
Asynchrone Interrupts (externe Interrupts) : von anderer Hardware außerhalb der CPU erzeugt, sagen wir das Klassen-Interrupts sind asynchron, was bedeutet, dass das Interrupt-Signal jederzeit ausgegeben werden kann, unabhängig vom Takt der CPU selbst. Zum Beispiel Unterbrechung der Uhr, Unterbrechung der Lese- und Schreibdienstanforderung der Festplatte usw.
Synchronischer Interrupt (interner Interrupt/Ausnahme ): Wird innerhalb der CPU generiert. Es wird gesagt, dass diese Art von Interrupt synchron ist, was bedeutet, dass die Übertragungszeit von Das Interrupt-Signal muss zum aktuellen Zeitpunkt vorliegen, nachdem die Befehlsausführung abgeschlossen ist. Im Allgemeinen entstehen sie durch interne Ereignisse der CPU oder Ereignisse während der Programmausführung, wie z. B. illegale Opcodes, Adressüberschreitungen, Gleitkommaüberlauf usw.
Synchronische Interrupts (Ausnahmen) werden in die folgenden Kategorien unterteilt:
Vom Prozessor erkannte Ausnahmen: Der Prozessor ist Während der Ausführung von Anweisungen erkannte Unterbrechungen, z. B. eine Division durch Null-Operation.
Fehler: Ein abnormaler Zustand tritt auf, aber nachdem der abnormale Zustand behoben wurde, kann der ursprüngliche Programmablauf ohne Auswirkungen, wie z. B. das Fehlen einer abnormalen Seite, weiter ausgeführt werden . Beachten Sie, dass der Befehl, der den Interrupt ausgelöst hat, erneut ausgeführt wird.
Traps: Unterbrechungen, die durch abgefangene Anweisungen verursacht werden und normalerweise zum Debuggen von Programmen verwendet werden.
Abbrüche: Ein wichtiger Fehler tritt innerhalb der CPU auf, beispielsweise ein Hardwarefehler oder ein Fehler im Systemtabellenwert. Sobald diese Unterbrechung auftritt, ist der Fehler nicht mehr behebbar und der aktuelle Prozess kann nur noch beendet werden.
Programmierte Ausnahmen: auch bekannt als Software-Interrupts (Soft-Interrupts), aktiv durch den Code des Programmierers initiierte Interrupts, die zur Implementierung von Systemaufrufen verwendet werden . Unter Linux wird beispielsweise die Anweisung int 0x80
verwendet, um Systemaufrufe zu implementieren.
Bisher haben wir den Zusammenhang zwischen Interrupts und Systemaufrufen entdeckt: Systemaufrufe sind eine besondere Art von Interrupt (Soft-Interrupt) .
5. Kernel-Verarbeitung von Systemaufrufen
In x86-Maschinen wird eine 8-Bit-Zahl (0~255) zur Unterscheidung verwendet Bei verschiedenen Interrupts wird diese Zahl als Interrupt-Vektor bezeichnet. Einer der Interrupt-Vektoren, 128 (0x80), wird speziell zur Ausführung von Systemaufrufen verwendet.
Im Linux-System gibt es eine Systemtabelle namens Interrupt DescriptorTable, die als IDT bezeichnet wird. Es gibt 256 Einträge in der IDT-Tabelle, die die Zuordnungsbeziehung von Interrupt-Vektoren zu entsprechenden Verarbeitungsroutinen (Interrupt oder Ausnahmehandler) speichert. Wenn ein Interrupt auftritt, ermittelt die CPU die Adresse der entsprechenden Verarbeitungsroutine aus der IDT-Tabelle und führt sie aus.
Die Systemaufrufverarbeitungsroutine belegt einen Eintrag in der IDT-Tabelle. Dieses Element wird in der Funktion trap_init wie folgt initialisiert: set_system_gate(SYSCALL_VECTOR,&system_call);
. Wie bereits erwähnt, beträgt der Wert von SYSCALL_VECTOR im obigen Code 128.
Wenn ein Systemaufruf auftritt, wird die Systemaufrufroutine system_call über den Interrupt-Mechanismus aufgerufen. Der Ausführungsprozess ist grob in 4 Schritte unterteilt:
1. Nehmen Sie die Systemaufrufnummer und die Eingabeparameter aus dem Register und übertragen Sie dann die Werte dieser Register in den Kernel-Stack. Durchsuchen Sie die Systemaufruf-Verteilungstabelle nach der Systemaufrufnummer und finden Sie die Systemaufruf-Dienstroutine (eine Kernelfunktion).
2. Rufen Sie die gefundene Systemaufruf-Serviceroutine auf.
3. Nehmen Sie den Rückgabewert der Systemaufruf-Serviceroutine vom Stapel und speichern Sie ihn erneut im Register.
Die oben beschriebene Systemaufrufroutine system_call wird im Kernelraum ausgeführt. Vor der Ausführung wurden die Systemrufnummer und die Eingabeparameter im Register gespeichert, und dieser Speichervorgang wird durch den Benutzerraumcode abgeschlossen. Tatsächlich verfügt jeder echte Systemaufruf, wie im ersten Abschnitt erwähnt, grundsätzlich über eine Bibliotheksfunktion, die ihn kapselt. Im Allgemeinen werden die Systemaufrufnummer und die Eingabeparameter in dieser Bibliotheksfunktion gespeichert. Wenn die Systemaufrufroutine system_call ausgeführt wird, wird der Rückgabewert über das Register an die User-Space-Bibliotheksfunktion zurückgegeben.
Das obige ist der detaillierte Inhalt vonWas ist der Zweck des Systemaufrufs?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!