Professional Documents
Culture Documents
Zusammenfassung Betriebsystemtechnik FAU SS18 PDF
Zusammenfassung Betriebsystemtechnik FAU SS18 PDF
1
• once the kernel is loaded into memory and executing, it can start providing services to
the system and its users
- some services are provided outside of the kernel, by system programs that are loaded
into memory at boot time to become system processes, or system daemons that run the
entire time the kernel is running
2 Betriebssystemarchitektur
• ein Operationsprinzip für die Systemsoftware welches sich in der Rechnerbetriebsart ma-
nifestiert
2.1 Architektur
Eine damit gemeinte Konstruktion ist auf drei Prinzipien begründet:
Eine Betriebssystemarchitektur ist bestimmt durch ein Operationsprinzip für die Systemsoft-
ware und die Struktur ihres Aufbaus aus den einzelnen Systemprogrammen.
• Betriebs-/Angriffssicherheit (safety/security)
2.3 Architekturformen
Monolithische Systeme allgemein
• als eine Menge von Prozeduren realisiert
2
Allgemeine Struktur des Aufbaus
• Privilegiensystem
- Systemmodus ⇔ Anwendungsmodus
- Direkter Hardwarezugriff nur im Systemmodus ⇒ Gerätetreiber gehören zum System
Vorteile
Nachteile
3
- keinen sicherer Speicherschutz, nur Anwendungen isoliert
- viele Komponenten laufen überflüssigerweise im Systemmodus
• Eingeschränkte Synchronisationsmechanismen
- oft nur ein ’Big Kernel Lock’, d. h. nur ein Prozess kann zur selben Zeit im Kernmodus
ausgeführt werden, alle anderen warten
Architektureigenschaften
Monolithisches Betriebssystem
Ungetrennte Systemfunktionen
• einheitlicher Adressraum
• keine Fehlereingrenzung
• prozedur-/prozessorientierter Aufbau
4
Monolithisches schichtenstrukturiertes Betriebssystem
Ungetrennte Systemfunktionen
• einheitlicher Adressraum
• keine Fehlereingrenzung
• prozedur-/prozessorientierter Aufbau
• Programmhierarchie
• Benutzthierarchie
• funktionale Hierarchie
- nur Funktionen der nächsthöheren Schicht auf-
rufbar
• Systemkomponenten müssen nur so viele Privilegien besitzen, wie zur Ausführung ihrer
Aufgabe erforderlich sind
– z.B. Treiber: Zugriff auf spezielle IO-Register, nicht auf die gesamte HW
– Speicherverwaltung: Pflege der Übersetzungstabellen, Programmierung der MMU;
jedoch nicht die Prozessein - und -auslagerung
– Prozessverwaltung: insbesondere Dispatching; nicht jedoch Scheduling
– Unterbrechungsbehandlung: Externe Unterbrechungsanforderungen werden vom
Mikrokern entgegengenommen und über IPC an den zuständigen Server-Prozess
(Treiber) weitergeleitet
– Interprozesskommunikation: normalerweise botschaftsorientiert oder über (lokal ge-
nutzte) RPCs, und Prozessynchronisation zwischen Server-Prozessen
– sowie Grundfunktionen zur Synchronisation
5
• alle weiteren Funktionen werden in privilegierte, sogenannte Server-Prozesse mit eige-
nen Adressräumen ausgelagert, die mit den nachfragenden Programmen (Client) kom-
munizieren, oder als Programmbibliothek, welche von den nachfragenden Programmen
eingebunden wird, im Benutzer-Modus implementiert.
– Speicherverwaltung inklusive Paging
– Dateisystemverwaltung
– Interprozesskommunikation und -synchronisation zwischen Anwendungsprozessen
– Realisierung von Scheduling-Strategien
– Netzdienste
– Graphikfunktionen
– sonstige Ein-/Ausgabe
Vorteile
• Separierte Komponenten
6
– Flexibilität: Einzelne Bestandteile des Betriebssystems können beliebig ausgetauscht
werden, ohne dass dadurch andere Teile beeinträchtigt werden
– Der Absturz einer einzelnen Komponente führt nicht zwangsläufig zum Zusammen-
bruch des gesamten Systems
• Treiber im Benutzer-Modus
– Die Gerätetreiber laufen zusammen mit einem Anwendungsprogramm im Benutzer-
Modus – im Gegensatz zu Monolithischen Kerneln, bei denen alle Treiber im pri-
vilegierten Modus laufen. Dies hat den Vorteil, dass die Zugriffsrechte der Treiber
einzeln bestimmt werden können. Gerätetreiber brauchen nicht im Kernel zu sein
und sind meist so konzipiert, dass sie auch mit Benutzerrechten ausgeführt werden
können.
• Sicherheit:
– kleine Trusted Computing Base: Der Kernel-Code, dem ein Nutzer vertrauen muss,
ist im Vergleich zu monolithischen Betriebssystemen relativ klein und somit einfa-
cher zu verifizieren
– getrennte Adre Adressräume der Komponenten
• Gut geeignet für Verteilte Systeme: Leichte Verteilung von Betriebssystemdiensten auf
mehrere Rechner
• leichte Konfigurierbarkeit durch Abwahl nicht benötigter Komponenten
• Personalisierbarkeit durch mehrere koexistente API-Server, aber auch mehrere koexis-
tente Subsysteme
Nachteile
• Leistungsverluste: hoher Overhead für IPC-Operationen (Adressraumüberschreitung und
häufige Kontextwechsel)
7
Mikrokernbasiertes Betriebssystem
getrennte Systemfunktionen
• in separierten Adressräumen
• starke Fehlereingrenzung
• verschiedene Arbeitsmodi
- privilegierter Kern (dunkel)
- unprivilegierte Systemprozesse (hell)
mittelkörnige Struktur
8
Makrokernbasiertes Betriebssystem
• in separierten Adressräumen
• schwache Fehlereingrenzung
• verschiedene Arbeitsmodi
- privilegierter Hybridkern (dunkel)
- unprivilegierte Systemprozesse (hell)
eingeschränkte Modularität
grobkörnige Struktur
9
Exokernbasiertes Betriebssystem
• Betriebsmittelverwaltung
- durch Bibliotheksbetriebssysteme (hell)
• Betriebsmittelschutz
- durch den Exokern (dunkel)
konsequentes Freilegen
• von Betriebsmittelbindungen
• aller Betriebsmittelbelegungen
drei Grundtechniken:
1. sichere Betriebsmittelbindung
2. sichtbarer Betriebsmittelwiderruf
3. imperativer Betriebsmittelentzug
10
2.4 Dualität: Betriebssystemstruktur
Nachrichtenorientiertes System
11
Prozedurorientiertes System
12
Gegenüberstellung
3 Bindelader
3.1 Einleitung
13
shared memory segment
• explizite Text- und Datenverbünde ursprünglich getrennter Adressräume
- positionsabhängige/-unabhängige Mitbenutzung
Übertragungstechniken
• Prozessadressraumerzeugung: COW
• Deduplizierung: COW
shared library
• Programmbibliothek im Textverbund (code sharing)
14
Programmbibliotheken
Bündel von Unterprogrammen oder Objekten, die von Programmen durch symbolische Adres-
sierung angefordert werden
3.2 Background-Informationen
Objektdateien: nicht-ausführbare Binärdateien
• verschiebarer (relocatable) Maschinencode
• Vorteile:
- schneller Programmstart, weil dynamisches Laden entfällt
- einfacher zu verteilen, da Bibliotheken nicht vorinstalliert sein müssten
Relocation / Rebasing
Verschiebung von Code ist notwendig, falls Bibliotheken dieselben virtuellen Adressen bean-
spruchen
16
Relocation vs PIC
Es existieren zwei Konzepte um Adresskollisionen beim Laden dynamischer Bibliotheken auf-
zulösen:
• Relocatable Code
– data addressing
- A GOT ( global offset table)is simply a table of addresses, residing in the data
section. Suppose some instruction in the code section wants to refer to a variable.
Instead of referring to it directly by absolute address (which would require a relo-
cation), it refers to an entry in the GOT. Since the GOT is in a known place in the
data section, this reference is relative and known to the linker. The GOT entry, in
turn, will contain the absolute address of the variable
- we’ve gotten rid of a relocation in the code section by redirecting variable refe-
rences through the GOT
- Relocation happens only to the data section, which is writable and not shared
between processes anyway, so adding relocations to it does no harm. Moving re-
17
locations from the code section, however, allows to make it read-only and share it
between processes.
– function calls
- The Procedure Linkage Table (PLT) allows lazy resolution of functions
- PLT[n] is called and jumps to the address pointed to in GOT[n]
Definition of Linker
• input: object code generated by the Assembler
• links library functions contained by the source program to the built-in libraries
• combining/linking all object modules to generate a single executable file of the source
program
• 2 types:
– Linkage Editor:
- generates the relocatable, executable module
– Dynamic Linker:
- defers/postpones the linkage of some external modules until the load module/exe-
cutable module is generated
- here, linking is done during load time or run time
• when the linker creates a shared library, it doesn’t know in advance where it might be
loaded
- his creates a problem for the data and code references within the library, which should
be somehow made to point to the correct memory locations.
18
Definition of Loader
The program that has to be executed currently must reside in the main memory of the computer
• load the executable file/module of a program, generated by the linker, to the main memory
for execution
• 3 loading approaches:
– Absolute loading
- loads the executable file of a program into a same main memory location each
time (address mentioned in the binary image record)
- in case, the program is to be modified involving some insertion and deletion in the
program, then all the addresses of the program have to be altered
- simple to implement and efficient in execution
- the programmer must know and clearly specify to the translator (the assembler)
the address in the memory for inner-linking and loading of the programs → are
should take so that the addresses do not overlap
- for programs with multiple subroutines, the programmer must remember the abso-
lute address of each subroutine and use it explicitly in other subroutines to perform
linking
- if the subroutine is modified, the program has to assemble again from first to last.
– Relocatable loading
- the compiler or assembler does not produce actual main memory address but rela-
tive addresses
- The rel.dyn section of ELF is reserved for dynamic (load-time) relocations, to be
consumed by the dynamic loader
- faster than PIC
– Dynamic run-time loading
- the absolute address for a program is generated when an instruction of an exe-
cutable module is actually executed - very flexible, the loadable module/executable
module can be loaded into any region of main memory - the executing program
can be interrupted in between and can be swapped out to the disk and back to main
memory this time at a different main memory address
19
Gemeinschaftsbibliothek
Arbeitsteilung von Binder und Lader, um die Anzahl redundanter Programme zu reduzieren
und Speicherplatz zu sparen
4 Systemaufruf
4.1 Partielle Interpretation
Ein Betriebssystem implementiert die Maschinenprogrammebene, d.h., es übersetzt das für das
Betriebssystem kompilierte Anwendungsprogramm (das z.B. Systemaufrufe enthält) auf Be-
fehlssatzebene (das, was die CPU frisst). Dabei sind nur einzelne Eingriffe in den Programma-
blauf nötig (z.B. bei Traps, Interrupts oder Systemaufrufen); in der Regel läuft das Programm
selbstständig auf der CPU.
Der Rechner wird aufgefasst als eine abstrakte Maschine, die fortlaufend eine Sequenz von
Instruktionen abarbeitet. Die meisten dieser Instruktionen können direkt von der untersten
Schicht der Maschine (sprich dem Prozessor) verarbeitet werden - aber auch Betriebssyste-
moperationen wie z. B. write() werden als Instruktionen der abstrakten Maschine angesehen.
Der Prozessor stellt keine native Operation bereit, um den Inhalt eines Puffers in einen Da-
teideskriptor zu schreiben. Die write()-Instruktion muss also von einer Zwischenebene (sprich
dem Betriebssystem) interpretiert werden. Das geschieht dadurch, dass mithilfe eines Traps die
Kontrolle an das Betriebssystem abgegeben wird, das dann seinerseits eine Sequenz von Ma-
schineninstruktionen auslöst, die die gewünschte Operation erledigen. Danach geht die Kon-
trolle zurück an das Anwendungsprogramm, das die Ausführung seiner Instruktionssequenz
fortsetzt.
.
• partielle Interpretation = nur einzelne Teile des Programms werden vom Betriebssystem
20
Anlaufprozedur - Startup Code
• die Inbetriebsetzung der Bibliothek geschieht im Programmkontext:
1. sie ist Teil des Betriebssystems
2. des ablauffähigen Programms selbst, das gerade geladen wird
So ein Betriebssystemkern besteht aus mehreren Schichten und Komponenten. Einige davon
kümmern sich um Interrupts oder die Hardware. Diese laufen nativ und sind keiner partiellen
Interpretation unterworfen (durch was denn auch?). Wenn jetzt aber z.B. einer der genannten
Gerätetreiber eine Division durch Null auslöst, oder einen Page-Fault, dann werden die unteren
Schichten (Trap-Handler) des Betriebssystem sich darum kümmern müssen, ein Linux wird
davon nicht gleich komplett abstürzen. Die partielle Interpretation, die man von Anwendungs-
programmen kennt, findet also nur auf manchen Teilen des Betriebssystemcodes statt. Also:
Eingeschränkte (betrifft nicht den kompletten Teil des Betriebssystems) partielle Interpretati-
on.
21
Positionsabhängigkeit
Eigenschaft von Programmtext, der abhängig von seiner absoluten Lage in einem Adress-
raum ausführbar ist
.
• Teilinterpretation von Betriebssystemprogrammen = Wenn ein Teil des Betriebssystems
einen Trap auslöst, dann wird zum Trap-Handler gesprungen. Die den Trap auslösende
Instruktion ist also indirekt (da durch die Hardware umgesetzt) ein rekursiver Aufruf in
einen anderen Betriebssystemcodepfad.
22
Positionsunabhängigkeit
Motiv: Verwendung von absoluter Adressierung (Text) oder absoluten Adressen (Daten) legt
Programmbereiche fest
• Relokation zur Laufzeit ist zwar möglich, aber oft nicht praktikabel
– es müssen alle zu ändernden Programmadressen bekannt sein
- für Programmtext stehen diese in der Symboltabelle des Binders (Sofern nicht
mittels strip(1) aus dem Objekt-/Lademodul entfernt)
- für Programmdaten sind dynamische Datenstrukturen zu verfolgen
→ Programme werden dann nicht unverfälscht (pure) ablaufen können
– aber nicht alle Adressen eines Programms liegen wirklich offen
– Ladezeit
- Verschiebung (relocation) der Bibliotheken
- Auflösung (resolution) von Programmsymbolen
– Laufzeit
- Entschleunigung durch Einsprungtabelle
- Mehraufwand durch Funktionsprolog
- Mehraufwand durch indirekte Datenreferenzen
- Verlangsamung durch reservierte Adressregister
4.2 Syscall
Syscalls in Linux
A system call is an entry point into the Linux kernel. Usually, system calls are not invoked
directly: instead, most system calls have corresponding C library wrapper functions which per-
form the steps required (e.g., trapping to kernel mode) in order to invoke the system call. Thus,
making a system call looks the same as invoking a normal library function.
23
Zusammenhang zur Gemeinschaftsbibliothek
Profiteur, wenn überhaupt, von positionsunabhängigem Kode ist die dynamische Gemein-
schaftsbibliothek (dynamic shared library)
Gegenstück dazu ist die - durch positionsunabhängigen Kode unnötig belastete - statische Ge-
meinschaftsbibliothek (static shared library)
Gemeinsamkeit:
- der Programmtext wird zur Lade- oder Laufzeit eingeblendet
24
•
In many cases, the C library wrapper function does nothing more than:
• copying arguments and the unique system call number to the registers where the kernel
expects them;
• trapping to kernel mode, at which point the kernel does the real work of the system call;
• setting errno if the system call returns an error number when the kernel returns the CPU
to user mode.
However, in a few cases, a wrapper function may do rather more than this, for example,
performing some preprocessing of the arguments before trapping to kernel mode, or postpro-
cessing of values returned by the systemcall.
Allgemein
• adressraumübergreifender Prozeduraufruf
25
Syscalls in Linux
Ortstransparenz
• für den Aufrufer durch den Auf-
rufstumpf
Entkopplung
• des Maschinenprogramms von Pro-
grammen des Betriebssystems
Zugriffstransparenz
• für den Aufrufzuteiler
Betriebssystem-Befehlsart
Komplexbefehl (CISC-artig)
• Dispatcher muss Operanden aus Befehlsstrom lesen und den Befehlszähler des Maschi-
nenprogrammes P Cos inkrementieren
– Zugriff auf P Cos und damit auf Opcode und Operandenliegt mittels BS-Stack
26
– Überschreiben des auf dem BS-Stack liegenden Wertes von P Cos vor dem Return
– beim iret stellt die CPU ihren zuvor gesicherten Status wieder her (P Ccpu = P Cos
– muss Kenntnis darüber besitzen, welcher Operand wie zu adressieren ist (unmittel-
bar vs direkt)
• Möglichkeit 1: 2 unterschiedliche Syscalls
– Direkte Systemaufrufe verwenden die unmittelbare Adressierung, die Operanden
sind Teil des Systemaufrufbefehls und liegen im Textsegment. Indirekte System-
aufrufe geschehen durch zwei verknüpfte Systemaufrufbefehle. Der erste Befehl
(Textsegment) verwendet die direkte Adressierung, um einen Deskriptor für den
zweiten Befehl (Datensegment) zu referenzieren. Dieser Hauptbefehl hat den Ope-
rationskode mit Nummer 0 und veranlasst den Syscall-Dispatcher dazu, den direkt
adressierten und im Deskriptor kodierten Nebenbefehl, der die eigentlich zu star-
tende Systemfunktion identifiziert, zur Ausführung zu bringen. Die Auswertung
der somit durch einen Referenzparameter (nämlich der einzige Operand des Haupt-
befehls) adressierten Operanden des Nebenbefehls kann zur Laufzeit geschehen
• Möglichkeit 2: Einkodierung in den Opcode
– Angenommen, das den Operationskode tragende Argument (opc ) ist 32 Bits breit,
wovon der Operationskode die niederwertigen 8 Bits beansprucht. Dann bleiben
24 Bits zur Klassifizierung von bis zu 24 Operanden beispielsweise mit folgender
Bedeutung: 0 für unmittelbare und 1 für direkte Adressierung.
• ⇒ Operandenauswertung im Dispatcher (⇔ Primitivbefehl)
• Ein Nachteil liegt im Falle von strikt privat eingerichteten Adressräumen vor, da zum
Abruf des Systemaufrufbefehls und seiner Operanden durch den Syscall-Dispatcher der
Adressraum des jeweiligen Benutzerebenenprozesses erst zugänglich gemacht werden
muss. Die dafür notwendigen Schritte sind vergleichsweise zeitaufwändig und erhöhen
die Latenz für einen Syscall durchaus erheblich.
• Fehlererkennung mittels Zustandsmerker im Statusregister
Primitivbefehl (RISC-artig)
27
• Anzahl der zu sichernden nichtflüchtigen (callee-save) Register
• Hauptspeicher oder flüchtige (caller-save) Register als Sicherungspuffer
• stapel- oder registerbasierte Parameterübergabe
• rückkehrende oder rückkehrlose Interaktion mit dem Betriebssystem
• Auswertung der direkten Operanden durch den Systemaufrufstumpf (Benutzerebene)
– Speicherung entweder in Registern
oft feste Zuordnung zwischen Argument und Prozessorregister für alle Systemauf-
rufe (Effizienz)
Sicherung der Registerinhalte auf Benutzerebene im Stub
Einschränkung der Parameteranzahl (6)
Übergabe zusätzlicher Parameter (7-n) über Stack
– oder auf dem Stack (Indirekter Syscall)
Return-Address in edx (sysenter)
Stackpointer in ecx (sysenter)
kopieren der Argumente auf den BS-Stack
ähnlich Komplexbefehl, allerdings kopieren von Stacksegment, nicht Textsegment
– int num in eax
• Fehleranmerkung per Wertebereich über Rückgabewert
– zweigeteilte Zielmenge für den Rückgabewert
ok error
z }| { z }| {
k
N0 = {0; 1; 2; · · · ; n} ∪ {n + 1; · · · ; 2 − 1}
k = Wortbreite, n = 4096 (Linux)
betriebssystemseitig einfach, sofern alle Funktionsergebnisse dazu passen
• call by value: die Systemaufrufparameter sind ausnahmslos Wertparameter, die bei der
Operandenauswertung gewonnen und als Kopien an den Systemaufrufzuteiler in Prozes-
sorregistern übergeben werden
• Dispatcher kopiert Operanden auf BS-Stack ⇒ Aufruf der Systemfunktion als gewöhn-
liches Unterprogramm
– Opcode Index für Sprungvektor, welcher die Funktions-Adressen enthält
– Vektortabelle hat 2v Einträge, v = Anzahl Bits der Syscall-Nummer im Opcode
(z.B. 8 ermöglicht 256 Syscalls)
– ungenutzte Syscall-Nummern werfen den Fehlercode ENOSYS
– Platzhalter für den Fehlerkode (im Datensegment, .data): .long errno
• oder mittels Carry Flag im Statusregister
– Stackframe des Systemaufrufs so manipulieren, dass bei Rückkehr der Merker den
Ausnahme- (1) oder Normalfall (0) anzeigt
28
– betriebssystemseitig mit größerem Overhead verbunden
stub : ; ops on s t a c k
p u s h l %ebx , %edi , %e s i , %ebp ; backup c a l l e e − save r e g i s t e r
.end :
p o p l %ebx , %edi , %e s i , %ebp ; r e s t o r e c a l l e e − save r e g i s t e r
ret
dispatcher :
p u s h l %ebp ; pass or just save 6th operand
p u s h l %e d i ; pass or just save 5th operand
p u s h l %e s i ; pass or just save 4th operand
p u s h l %edx ; pass or just save 3rd operand
p u s h l %ecx ; pass or just save 2nd operand
p u s h l %ebx ; pass or just save 1st operand
asmlinkage
Instruiert gcc, die Funktionsparameter auf dem Stapel zu erwarten und nicht in Prozessorregis-
tern.
29
Primitivbefehl, Werteübergabe mittels Register
30
Primitivbefehl, Werteübergabe mittels Userstack
31
Komplexbefehl
Primitivbefehl vs Komplexbefehl
32
Ergänzend: Komplexbefehl
Im Gegensatz zum Primitivbefehl, bei dem die Operandenauswertung im Systemaufruf- stumpf
geschieht, erfolgt diese Auswertung für die hier betrachtete Variante im System- aufrufzutei-
ler. Wären Stumpf wie auch Zuteiler demselben Adressraum zugeordnet, ergäbe sich zwischen
beiden Varianten kaum ein Unterschied. Jedoch liegt zwischen diesen beiden Komponenten
nicht nur eine logische, sondern auch eine physische Grenze, die durch die Art der im Sys-
tem etablierten Adressraumisolation definiert ist. Folgt die Abkapselung eines Prozesses einem
Mehradressraummodell, bestimmt letztlich der Grad der den Prozessen 105damit gegebenen
Privatspähre, ob die Operandenauswertung auch für den Systemaufrufzu- teiler vergleichswei-
se einfach ist. Dies ist etwa der Fall, wenn die Adressräume für die auf Benutzerebene statt-
findenden Prozesse teilprivat und damit für Aktionen der Systemebe- ne, eben die Operanden-
auswertung im Systemaufrufzuteiler, direkt zugänglich sind (Linux, Windows NT). Im Falle
von strikt privat eingerichteten Adressräumen (UNIX V6, macOS) muss zum Abruf des Sys-
temaufrufbefehls und seiner Operanden durch den Systemaufruf- zuteiler der Adressraum des
jeweiligen Benutzerebenenprozesses erst zugänglich gemacht werden. Die dafür notwendigen
Schritte sind vergleichsweise zeitaufwändig und erhöhen die Latenz für einen Systemaufruf
durchaus erheblich
Der erste Maschinenbefehl nach der Operandenliste, deren Länge vom jeweiligen, durch den
Operationskode opc bestimmten Systemaufruf abhängt, prüft für gewöhnlich ab, ob während
der Durchführung des Systemaufrufs ein Fehler aufgetreten ist. Gegebenenfalls wird dann die
Fehlerbehandlung im Kontext des Maschinenprogramms eingeleitet. Diese Kodierungsform
impliziert einen Systemaufrufzuteiler, der zur Ausführung des Sys- temaufrufs die Operanden
aus den Befehlsstrom lesen und dabei den vom Betriebssystem verwalteten Befehlszähler des
Maschinenprogramms, P Cos , Schritt für Schritt weiterschal- ten muss, so dass bei Rückkehr
zur Benutzerebene der Maschinenbefehl zur Fehlerabfra- ge (jc) als nächster ausgeführt wird.
Damit ähnelt ein solcher Systemaufrufbefehl einem gewöhnlichen Maschinenbefehl, nur dass
er durch das Betriebssystem und nicht von der CPU interpretiert wird. Die für seine partielle
Interpretation erforderlichen Schritte folgen weitesgehend dem Befehlszyklus einer CPU, die
durch den von ihr verwalteten Befehlszähler, P Ccpu , auch zunächst den Operationskode lesen
und deuten muss, um so einerseits die Ope- ration und anderseits die Adressierungsart des oder
der Operanden zu identifzieren und nach Befehlsausführung im Statusregister die Zustandsan-
zeige (carry bit) in Bezug auf die durchgeführte Berechnung zu hinterlassen. Analog zur CPU,
die P Ccpu nach jeden dieser Abrufschritte implizit weiterschaltet, funktioniert der Systemauf-
rufzuteiler: schritt- weise setzt er den Zeiger automatisch weiter, so dass am Ende, wenn der
komplette System- aufrufbefehl gelesen wurde, der diesem Befehl nachfolgende Maschinen-
befehl (jc) adressiert wird.
Ergänzend: Primitvbefehl
Die für die hier betrachtete Art von Systemaufrufbefehl erfolgende Operandenauswertung auf
Benutzerebene bedeutet, dass nicht der Systemaufrufzuteiler, sondern der Systemauf- rufstumpf
33
den Abruf der Operanden bewerkstelligt. Durch die direkte Einbindung des Stump- fes in das
Maschinenprogramm und dem daraus resultierenden gemeinsamen Adressraum ist der Operan-
denzugriff sehr einfach. Die Systemaufrufparameter sind ausnahmslos Wert- parameter, die bei
der Operandenauswertung gewonnen und als Kopien an den Systemauf- rufzuteiler in Prozes-
sorregistern übergeben werden (call-by-value). Das Gegenstück im Systemaufrufzuteiler legt
nur die Inhalte der Prozessorregister auf dem Laufzeitstapel des Betriebssystems ab und kom-
plettiert damit praktisch die Parameterüber- gabe an die Systemfunktion, bevor diese als ge-
wöhnliches Unterprogramm aufgerufen wird. Dabei identifiziert der Operationskode, genauer
die in ihm enthaltene Systemaufrufnummer, letztlich die aufzurufende Systemfunktion. Die
Funktionsadresse steht in einem Sprungvek- tor, der mit der Systemaufrufnummer als Index
einem Zeigerfeld entnommen wird.
4.3 Schutzdomänenwechsel
reale Sicht: ursprünglicher Zweck von Systemaufrufen (um 1955)
• transiente Maschinenprogramme und residente Systemsoftware trennen
34
- Ring wechseln (aus IDT)
- Auf Kernel-Stack wechseln (Task State Segment, adressierbar über Deskriptor in
GDT)
- Zustand auf Stack sichern
– iret
- Kernel-Stack: ss, esp, eflags, cs, eip
- Rücksprungadresse vom Stack holen
- Flagregister rekonstruieren
- Auf Userspace-Stack zurückschalten
- Prioritätslevel wieder auf 3 setzen
35
/ / syscalls with sysenter / sysexit
wrmsr ( MSR_IA32_SYSENTER_CS, KERNEL_CODE_SEGMENT * 8 , 0 ) ;
wrmsr ( MSR_IA32_SYSENTER_EIP , ( unsigned l o n g ) s y s e n t e r _ d i s p a t c h e r , 0 ) ;
wrmsr ( MSR_IA32_SYSENTER_ESP, s t a c k _ p t r , 0 ) ;
...
s t a t i c v o i d wrmsr ( u i n t 3 2 _ t i d , u i n t 6 4 _ t v a l ) {
asm v o l a t i l e ( ` ` wrmsr ` ` : : ` `A ` ` ( v a l ) , ` ` c ` ` ( i d ) : ` ` memory ` ` ) ;
}
4.4 Resümee
Rekapitulation
• Maschinenprogramme werden durch Betriebssysteme teilinterpretiert
funktionale Hierarchie
• Systemaufrufstümpfe trennen Maschinenprogramm von Betriebssystem
Implementierung
• ein Systemaufruf ist als Primitiv- oder Komplexbefehl realisiert
36