Systemaufruf

Systemaufruf

Ein Systemaufruf, auch Systemcall (von engl. system call) oder kurz Syscall, ist in der Computertechnik eine von Anwendungsprogrammen benutzte Methode, um vom Betriebssystem bereitgestellte Funktionalitäten auszuführen, wie etwa das Lesen einer Datei. Dabei wird die Kontrolle vom Programm an das Betriebssystem übergeben.[1]

Inhaltsverzeichnis

Details

In modernen Computersystemen (z. B. der IA-32-Architektur von Intel) läuft der Kernel, also der Betriebssystemkern, im so genannten privilegierten Ring 0 (auch Kernel-Modus genannt) und hat damit Zugriff auf den kompletten Befehlssatz der CPU und den gesamten Speicherbereich. Aus Sicherheitsgründen laufen normale Benutzerprozesse dagegen in den unprivilegierten Ringen 1 bis 3 (Benutzer-Modus), in denen ihnen weniger Befehle zur Verfügung stehen und sie daher gewisse Aufgaben nicht direkt erledigen können. Muss ein im Benutzer-Modus laufender Prozess eine Aufgabe erfüllen, die nur in einem höher privilegierten Ring möglich ist, wie z. B. der Zugriff auf die Festplatte oder andere Hardware, kann er dies dem Kernel durch einen Systemaufruf mitteilen und so einen Kontextwechsel veranlassen. Dabei gibt der Prozess die Kontrolle über die CPU an den Kernel ab und wird so lange unterbrochen, bis die Anfrage komplett bearbeitet ist. Nach dem Systemaufruf gibt der Kernel die CPU wieder an den Prozess im Benutzer-Modus ab und führt den Programmcode an der Stelle fort, an der der Kontextwechsel zuvor gefordert wurde. Zu keiner Zeit verlässt der Prozess seinen unprivilegierten Ring und kann so auch nicht Gefahr laufen, andere Prozesse oder gar die Stabilität des Systemkerns selbst zu gefährden, da nur vertrauenswürdiger Code aus dem Kernel im privilegierten Modus ausgeführt wird.

Ein Systemaufruf kann sowohl dafür zuständig sein, Informationen an die Hardware, den Kernel selbst oder andere Prozesse zu schicken, als auch solche zu lesen. Dafür ist es manchmal notwendig, Daten aus dem privaten Speicherbereich des Kernels, auf den ein normaler Prozess keinen Zugriff hat, in den Adressbereich eines Prozesses zu kopieren, damit der Prozess auch nach dem Aufruf noch Zugang zu den Daten hat und mit den Ergebnissen seiner Anfrage überhaupt etwas anfangen kann. Auch dies ist eine Folge der strikten Trennung zwischen Kernel-Modus und Benutzer-Modus.

Alle POSIX-kompatiblen Betriebssysteme müssen bestimmte Aufrufe implementieren, damit eine gewisse Portabilität zwischen den Systemen gewährleistet ist. Viele Hersteller fügen dem Standard aber auch eigene Erweiterungen hinzu, um dem Programmierer zusätzliche Möglichkeiten zu eröffnen. Im Linux-Kernel 2.6 für die x86-Architektur sind momentan 326 Aufrufe definiert.[2] Die Anzahl der Systemaufrufe in Microsoft Windows Vista beträgt laut inoffiziellen Quellen 360.[3]

Bibliotheksfunktionen

Die meisten Systeme stellen eine Programmierschnittstelle (API) für Systemaufrufe in Form von Bibliotheksfunktionen zur Verfügung, die es einem Programmierer erleichtern, Arbeiten zu erledigen, die einen erweiterten Zugriff auf den Befehlssatz der CPU erfordern.

Häufig verwendete Funktionen (beispielsweise unter POSIX), die auf Systemaufrufen basieren, sind unter anderem die Dateiverarbeitungsfunktionen open, close, read und write, sowie exec, fork oder exit. Diese können vom Programmierer wie normale Benutzer-Modus-Funktionen genutzt werden, führen aber unbemerkt im Hintergrund einen Kontextwechsel durch. Die Abkapselung der Systemaufrufe über eine API befreit den Programmierer vollständig von Überlegungen über die interne Funktionsweise des Betriebssystems oder der Hardware und erlaubt eine abstraktere Softwareentwicklung.

Die meisten dieser POSIX-Funktionen haben äquivalente Entsprechungen unter Win32. time unter POSIX entspricht beispielsweise GetLocalTime unter Win32.[4]

Implementierung

Die Implementierung von Systemaufrufen hängt stark von der verwendeten Hardware, der Architektur und letztlich auch dem benutzten Betriebssystem ab. In der Regel wird heute ein Systemaufruf mit Softwareinterrupts oder anderen Spezialinstruktionen der CPU realisiert. Bei älteren Systemen findet meist einfach nur ein Sprung an eine fest definierte Adresse statt, an der der Systemaufruf oder ein Sprungbefehl zu diesem implementiert ist. Für einen Programmierer, der die zur Verfügung gestellte Programmierschnittstelle des Betriebssystems nutzt, ist die Implementation von Systemcalls irrelevant.

In den Beispielen wird eine geöffnete Datei mit dem Dateideskriptor/Handle 15 geschlossen.

Linux

Der Linux-Kernel beherbergt eine Liste aller ihm bekannten Systemaufrufe, die so genannte System Call Table. Jedem Systemaufruf wird dort eine eindeutige Nummer und eine Kernel-interne Funktion zugeordnet, die für die eigentliche Erledigung der erforderlichen Aufgaben zuständig ist. Um einen Systemcall durchzuführen, wird die Nummer des gewünschten Aufrufs in das EAX-Register der CPU gespeichert und anschließend der Softwareinterrupt 128 (in hexadezimaler Schreibweise 0x80) ausgelöst. Argumente an den Systemaufruf werden gemäß der FastCall-Aufrufkonvention in den CPU-Registern abgelegt.

Der Softwareinterrupt (auch Exception genannt) unterbricht die Programmausführung im Benutzer-Modus und erzwingt das Ausführen eines Exception-Handlers im Kernel-Modus. Dadurch wird der Kontextwechsel von einem unprivilegierten Ring auf Ring 0 gewährleistet. Der aufgerufene Exception-Handler ist eine Funktion im Kernel, die das EAX-Register ausliest und dann, sofern sich darin eine gültige Systemaufruf-Nummer befindet, die entsprechende Kernel-Funktion aus der System Call Table mit den in den weiteren Registern liegenden Argumenten aufruft. Nach der Überprüfung der Argumente werden letztlich die aus dem Benutzer-Modus angeforderten Aufgaben vom Kernel erledigt. Kehrt diese Funktion zurück, wird auch der Exception-Handler erfolgreich abgeschlossen und der normale Programmfluss im unprivilegierten Modus fortgesetzt.

mov $6,  %eax    ; close() ist Systemaufruf 6
mov $15, %ebx    ; Dateideskriptor als erstes Argument
int $0x80        ; Softwareinterrupt auslösen

Softwareinterrupts haben aber nur eine sehr geringe Ausführungsgeschwindigkeit. Deshalb haben sowohl Intel als auch AMD in ihren x86-Prozessoren Befehle implementiert (sysenter/sysexit, bzw. syscall/sysret, letztere beiden erst ab der 64-Bit-Architektur AMD64), die die Aufrufe beschleunigt durchführen können. Da jedoch nicht jeder x86-Prozessor einen kompatiblen Befehl unterstützt, wird bei aktuellen Linux-Versionen die sogenannte vsyscall-Page verwendet, in der der für die benutzte Architektur passende Code hinterlegt wird.[5][6] Wenn ein Programm nun einen Systemcall ausführen will, springt es zu dieser Speicherseite und führt dort den Programmfluss fort.

Unix und Unix-Varianten

Bei vielen Unix-Varianten (z.B. älteren Solaris-Versionen) wird eine sogenannte "call gate" verwendet. Dabei verwendet die Anwendung (im Ring 3) einen Sprungbefehl an eine spezielle Adresse, die das Call-Gate beschreibt.

Call Gates sind zwar schneller als Software-Interrupts (Cyrix 6x86: 23%), benötigen jedoch 7 anstatt 2 Bytes Code.

Neuere Solaris-Versionen beherrschen alternativ Software-Interrupts sowie Syscall und Sysenter-Befehle.

Windows

Systemaufrufe in Microsofts Windows werden ähnlich wie in Linux gehandhabt. Die im Programmcode aufgerufene Bibliotheksfunktion aus der Windows API wird zunächst intern in einen Aufruf der so genannten Native API umgewandelt. Dort wird eine für jeden Aufruf eindeutige Nummer in das EAX-Register gelegt und ein Zeiger auf die Argumente für die Funktion im EDX-Register gespeichert. Über die Assembler-Instruktion sysenter wird die Kontrolle aus dem Benutzer-Modus an den privilegierten Kernel abgegeben, der die Parameter überprüft und anschließend eine der im EAX-Register liegenden Nummer zugeordnete Kernel-Funktion ausführt.

 mov eax, 0x2f    ; NtClose() trägt die Nummer 0x2f in Windows Vista
 push 15          ; 15 auf den Stack legen
 mov edx, esp     ; Pointer auf 15 in EDX speichern
 sysenter         ; Systemaufruf durchführen

Commodore

Beispielhaft für die Funktionsweise von Systemaufrufen in älteren Systemen sei hier die Methode der frühen Commodore-Rechner genannt. Die dort verwendeten Prozessoren der MOS Technology 6502-Familie kannten noch keine Unterscheidung zwischen Benutzer-Modus und Kernel-Modus und so war es möglich, die Kernel-internen Systemcall-Funktionen direkt aus dem normalen Programmfluss aufzurufen. Der einzige Sinn von Systemaufrufen war zu dieser Zeit daher nicht das Durchführen von Tätigkeiten, die bestimmte Privilegien verlangten, sondern eine vom Kernel implementierte Menge an standardisierten Funktionen bereitzustellen, die unabhängig von weiteren Bibliotheken sind und sich auch noch auf späteren Versionen des Systems benutzen lassen sollten (siehe auch bei Sprungtabelle).

Der Programmierer konnte, nachdem er die Argumente der Funktion in die entsprechenden CPU-Register gelegt hatte, einfach mittels des Assembler-Befehls JSR (Jump to SubRoutine), gefolgt von einer Adresse oder einem symbolischen Funktionsnamen, eine im Kernel-Adressraum liegende Routine anspringen. Zur Zeit von Commodore BASIC 4.0 gab es 28 Systemaufrufe.[7]

 LDA #15         ; 15 in das Register A legen
 JSR SYS4        ; Zur Kernel-Routine SYS4 (CLOSE) springen

Einzelnachweise

  1. A. Tanenbaum: Moderne Betriebssysteme. Pearson Studium, 2009, ISBN 978-3827373427, S. 85.
  2. http://lxr.linux.no/linux/arch/x86/kernel/syscall_table_32.S (1.  Oktober 2008)
  3. http://www.metasploit.com/users/opcode/syscalls.html (20. Juni 2007)
  4. A. Tanenbaum: Moderne Betriebssysteme. Pearson Studium, 2009, ISBN 978-3827373427, S. 97.
  5. http://www.linux-magazin.de/heft_abo/ausgaben/2004/08/kern_technik
  6. http://manugarg.googlepages.com/systemcallinlinux2_6.html
  7. http://www.commodore.ca/manuals/pdfs/Commodore_Basic_4_Users_Reference%20Manual.pdf, Anhang H (21. Juni 2007)

Wikimedia Foundation.

Игры ⚽ Поможем сделать НИР

Schlagen Sie auch in anderen Wörterbüchern nach:

  • Syscall — Ein Systemaufruf, auch Systemcall (von engl. system call) oder kurz Syscall, ist in der Computertechnik eine von Anwendungsprogrammen benutzte Methode, um vom Betriebssystem bereitgestellte Funktionalitäten auszuführen. Inhaltsverzeichnis 1… …   Deutsch Wikipedia

  • System Call — Ein Systemaufruf, auch Systemcall (von engl. system call) oder kurz Syscall, ist in der Computertechnik eine von Anwendungsprogrammen benutzte Methode, um vom Betriebssystem bereitgestellte Funktionalitäten auszuführen. Inhaltsverzeichnis 1… …   Deutsch Wikipedia

  • Systemcall — Ein Systemaufruf, auch Systemcall (von engl. system call) oder kurz Syscall, ist in der Computertechnik eine von Anwendungsprogrammen benutzte Methode, um vom Betriebssystem bereitgestellte Funktionalitäten auszuführen. Inhaltsverzeichnis 1… …   Deutsch Wikipedia

  • Kill (Unix) — kill (engl. töten) ist ein Unix Kommando und gleichnamiger Systemaufruf, um unter dem Betriebssystem laufenden Prozessen Signale zu schicken. Standardmäßig wird dabei das Signal SIGTERM versendet, welches den entsprechenden Prozess dazu… …   Deutsch Wikipedia

  • NPTL — Die Native POSIX Thread Library (NPTL) ist eine moderne Implementierung einer Threading Bibliothek für Linux. Sie wird in Verbindung mit der GNU C Library (glibc) verwendet und erlaubt Linux Programmen die Verwendung von POSIX Threads. Geschichte …   Deutsch Wikipedia

  • Port-Scanning — Ein Portscanner ist eine Software, mit der überprüft werden kann, welche Dienste ein mit TCP/IP oder UDP arbeitendes System anbietet. Der Portscanner nimmt dem Anwender dabei die Arbeit ab, das Antwortverhalten eines Systems selbst mit einem… …   Deutsch Wikipedia

  • Port scanning — Ein Portscanner ist eine Software, mit der überprüft werden kann, welche Dienste ein mit TCP/IP oder UDP arbeitendes System anbietet. Der Portscanner nimmt dem Anwender dabei die Arbeit ab, das Antwortverhalten eines Systems selbst mit einem… …   Deutsch Wikipedia

  • Portscan — Ein Portscanner ist eine Software, mit der überprüft werden kann, welche Dienste ein mit TCP/IP oder UDP arbeitendes System anbietet. Der Portscanner nimmt dem Anwender dabei die Arbeit ab, das Antwortverhalten eines Systems selbst mit einem… …   Deutsch Wikipedia

  • Portscanning — Ein Portscanner ist eine Software, mit der überprüft werden kann, welche Dienste ein mit TCP/IP oder UDP arbeitendes System anbietet. Der Portscanner nimmt dem Anwender dabei die Arbeit ab, das Antwortverhalten eines Systems selbst mit einem… …   Deutsch Wikipedia

  • Pthread — Die Native POSIX Thread Library (NPTL) ist eine moderne Implementierung einer Threading Bibliothek für Linux. Sie wird in Verbindung mit der GNU C Library (glibc) verwendet und erlaubt Linux Programmen die Verwendung von POSIX Threads. Geschichte …   Deutsch Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”