System Call

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

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öheren 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.[1] Die Anzahl der Systemaufrufe in Microsoft Windows Vista beträgt laut inoffiziellen Quellen 360.[2]

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, 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.

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 unter Linux die sogenannte vsyscall-Page verwendet, in der der für die benutzte Architektur passende Code hinterlegt wird.[3][4] Wenn ein Programm nun einen Systemcall ausführen will, springt es zu dieser Speicherseite und führt dort den Programmfluss fort.

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.[5]

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

Quellen

  1. http://lxr.linux.no/linux/arch/x86/kernel/syscall_table_32.S (1.  Oktober 2008)
  2. http://www.metasploit.com/users/opcode/syscalls.html (20. Juni 2007)
  3. http://www.linux-magazin.de/heft_abo/ausgaben/2004/08/kern_technik
  4. http://manugarg.googlepages.com/systemcallinlinux2_6.html
  5. 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:

  • System call — In computing, a system call is the mechanism used by an application program to request service from the kernel. Background A system call is a request made by any arbitrary program to the kernel for performing tasks picked from a predefined set… …   Wikipedia

  • system call — noun an instruction that interrupts the program being executed and passes control to the supervisor • Syn: ↑supervisor call instruction • Hypernyms: ↑call …   Useful english dictionary

  • Open (system call) — For most file systems, a program initializes access to a file in a filesystem using the open system call. This allocates resources associated to the file (the file descriptor), and returns a handle that the process will use to refer to that file …   Wikipedia

  • Close (system call) — For most file systems, a program terminates access to a file in a filesystem using the close system call. This flushes buffers, updates file metadata (which may include and end of file indicator in the data), de allocates resources associated… …   Wikipedia

  • Splice (system call) — splice() is a system call that copies data between a file handle and a pipe, or between a pipe and user space. It does so without actually copying the data, in contrast to other data copying techniques, thereby improving I/O performance.Workings… …   Wikipedia

  • clone (Linux system call) — clone() is a system call on the Linux kernel related to multithreading. In practice, one should try to avoid calling clone() directly, but instead use a threading library (such as pthreads) which use clone() when starting a thread (such as during …   Wikipedia

  • Clone (Linux system call) — clone() is a system call on the Linux kernel related to multithreading.The syntax for calling clone under a Linux program is: #include int clone (int (*fn) (void *), void *child stack, int flags, void *arg);clone creates a new thread that starts… …   Wikipedia

  • Call — may refer to: NOTOC Technology* Call (telecommunications) * Telephone call * Computer assisted language learning, a concept in language education * System call, the mechanism used by an application program to request service from the operating… …   Wikipedia

  • Call a Pizza — Franchise GmbH Rechtsform Franchise Gründung 1985 Sitz Berlin Leitung Thomas Wilde Umsatz …   Deutsch Wikipedia

  • Call gate — A call gate (or callgate) is a mechanism in Intel s x86 architecture for changing the privilege level of the CPU when it executes a predefined function call using a CALL FAR instruction. Overview Call gates are intended to allow less privileged… …   Wikipedia

Share the article and excerpts

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