Betriebssysteme: Drei einfache Teile. Teil 2: Abstraktion: Prozess (Übersetzung)

Einführung in Betriebssysteme


Hallo Habr! Ich möchte Sie auf eine Reihe von Artikelübersetzungen einer meiner Meinung nach interessanten Literatur aufmerksam machen - OSTEP. Dieser Artikel beschreibt ziemlich ausführlich die Arbeit von Unix-ähnlichen Betriebssystemen, nämlich die Arbeit mit Prozessen, verschiedenen Schedulern, Speicher und anderen ähnlichen Komponenten, aus denen das moderne Betriebssystem besteht. Das Original aller Materialien können Sie hier sehen . Bitte beachten Sie, dass die Übersetzung unprofessionell (ziemlich frei) durchgeführt wurde, aber ich hoffe, dass ich die allgemeine Bedeutung beibehalten habe.

Laborarbeiten zu diesem Thema finden Sie hier:

Andere Teile:

Und du kannst meinen Kanal im Telegramm ansehen =)


Betrachten Sie die grundlegendste Abstraktion, die das Betriebssystem den Benutzern bietet: einen Prozess. Das Definieren eines Prozesses ist ziemlich einfach - es ist ein Arbeitsprogramm . Das Programm selbst ist eine leblose Sache auf der Festplatte - es besteht aus einer Reihe von Anweisungen und möglicherweise statischen Daten, die darauf warten, gestartet zu werden. Es ist das Betriebssystem, das diese Bytes nimmt und startet und das Programm in etwas Nützliches konvertiert.
In den meisten Fällen möchten Benutzer mehr als ein Programm gleichzeitig ausführen. Sie können beispielsweise einen Browser, ein Spiel, einen Media Player, einen Texteditor und dergleichen auf Ihrem Laptop ausführen. Tatsächlich kann ein typisches System Dutzende und Hunderte von Prozessen gleichzeitig ausführen. Diese Tatsache erleichtert die Verwendung des Systems. Sie müssen sich keine Gedanken darüber machen, ob die CPU frei ist. Sie führen nur die Programme aus.

Dies wirft das Problem auf: Wie kann die Illusion mehrerer CPUs erzeugt werden? Wie erzeugt das Betriebssystem die Illusion einer nahezu unendlichen Anzahl von CPUs, selbst wenn Sie nur eine physische CPU haben?

Das Betriebssystem erzeugt diese Illusion durch CPU-Virtualisierung. Durch Starten eines Prozesses, anschließendes Stoppen, Starten eines anderen Prozesses usw. kann das Betriebssystem die Illusion unterstützen, dass es viele virtuelle CPUs gibt, obwohl es sich tatsächlich um einen oder mehrere physische Prozessoren handelt. Diese Technik wird als CPU-Time-Sharing bezeichnet . Mit dieser Technik können Benutzer so viele Prozesse gleichzeitig ausführen, wie sie möchten. Die Kosten einer solchen Lösung sind die Leistung - denn wenn die CPU von mehreren Prozessen gemeinsam genutzt wird, wird jeder Prozess langsamer verarbeitet.
Um die CPU-Virtualisierung zu implementieren und insbesondere um sie gut zu machen, benötigt das Betriebssystem sowohl Unterstützung auf niedriger als auch auf hoher Ebene. Low-Level-Unterstützung wird als Mechanismen bezeichnet. Hierbei handelt es sich um Low-Level-Methoden oder -Protokolle, die den erforderlichen Teil der Funktionalität implementieren. Ein Beispiel für eine solche Funktionalität ist die Kontextumschaltung, mit der das Betriebssystem ein Programm stoppen und ein anderes Programm auf dem Prozessor ausführen kann. Diese Zeiteinteilung ist in allen modernen Betriebssystemen implementiert.
An der Spitze dieser Mechanismen steht eine im Betriebssystem eingebettete Logik in Form von „Richtlinien“. Eine Richtlinie ist ein bestimmter Entscheidungsalgorithmus eines Betriebssystems. Solche Politiker entscheiden beispielsweise zunächst, welches Programm (aus der Befehlsliste) ausgeführt werden soll. So löst beispielsweise eine Richtlinie, die als Planungsrichtlinie bezeichnet wird, dieses Problem. Bei der Auswahl einer Lösung werden folgende Daten verwendet: Startverlauf (welches Programm wurde in den letzten Minuten am längsten ausgeführt), welche Art von Last dieser Prozess ausführt (welche Arten von Programmen wurden gestartet) ), Leistungsmetriken (unabhängig davon, ob das System für interaktive Interaktion oder für Bandbreite optimiert ist) und so weiter.

Abstraktion: Prozess


Die Abstraktion eines laufenden Programms, das vom Betriebssystem ausgeführt wird, wird als Prozess bezeichnet . Wie bereits erwähnt, ist ein Prozess zu jedem Zeitpunkt einfach ein Arbeitsprogramm. Ein Programm, mit dessen Hilfe wir zusammenfassende Informationen aus verschiedenen Ressourcen des Systems erhalten können und an das sich dieses Programm richtet oder das sich während seiner Ausführung auswirkt.
Um die Komponenten des Prozesses zu verstehen, müssen Sie den Status des Systems verstehen: dass das Programm während seines Betriebs lesen oder ändern kann. Zu jedem Zeitpunkt müssen Sie verstehen, welche Elemente des Systems für die Programmausführung wichtig sind.
Eines der offensichtlichen Elemente des Systemzustands, den der Prozess enthält, ist der Speicher . Die Anweisungen sind im Speicher. Die Daten, die das Programm ebenfalls liest oder schreibt, befinden sich im Speicher. Somit ist der Speicher, den der Prozess adressieren kann (der sogenannte Adressraum), Teil des Prozesses.
Register sind ebenfalls Teil des Systemstatus. Viele Anweisungen zielen darauf ab, die Bedeutung der Register zu ändern oder ihre Bedeutung zu lesen, und daher werden die Register auch ein wichtiger Teil des Prozesses.
Es ist zu beachten, dass der Zustand der Maschine auch aus einigen speziellen Registern gebildet wird. Beispiel: IP - Anweisungszeiger - Ein Zeiger auf die Anweisung, die das Programm gerade ausführt. Es gibt auch einen Stapelzeiger und den zugehörigen Rahmenzeiger , mit denen Folgendes gesteuert wird: Funktionsparameter, lokale Variablen und Rücksprungadressen.
Schließlich greifen Programme häufig auf das ROM (Nur-Lese-Speicher) zu. Solche Informationen zu „E / A“ (Eingabe / Ausgabe) sollten eine Liste der Dateien enthalten, die derzeit vom Prozess geöffnet werden.

Prozess-API


Um das Verständnis des Prozesses zu verbessern, untersuchen wir Beispiele für Systemaufrufe, die in jeder Schnittstelle des Betriebssystems enthalten sein sollten. Diese APIs in der einen oder anderen Form sind auf jedem Betriebssystem verfügbar.

Erstellen : Das Betriebssystem muss eine Methode enthalten, mit der Sie neue Prozesse erstellen können. Wenn Sie einen Befehl in das Terminal eingeben oder die Anwendung durch Doppelklicken auf das Symbol starten, wird ein Aufruf an das Betriebssystem gesendet, um einen neuen Prozess zu erstellen und dann das angegebene Programm zu starten.
Löschen : Sobald eine Schnittstelle zum Erstellen eines Prozesses vorhanden ist, sollte das Betriebssystem auch die Möglichkeit bieten, das Löschen eines Prozesses zu erzwingen. Die meisten Programme werden natürlich selbst gestartet und abgeschlossen, sobald sie ausgeführt werden. Andernfalls möchte der Benutzer sie töten können, und daher ist die Schnittstelle zum Stoppen des Prozesses nicht überflüssig.
Warten : Manchmal ist es hilfreich, auf den Abschluss des Vorgangs zu warten, sodass einige Schnittstellen bereitgestellt werden, die das Warten ermöglichen.
Sonstige Kontrolle (Sonstige Kontrolle): Neben dem Beenden und Warten auf den Prozess gibt es verschiedene andere Kontrollmethoden. Beispielsweise bieten die meisten Betriebssysteme die Möglichkeit, einen Prozess einzufrieren (für einen bestimmten Zeitraum anzuhalten) und dann fortzusetzen (Ausführung fortzusetzen).
Status : Es gibt verschiedene Schnittstellen, über die Sie Informationen zum Status des Prozesses erhalten können, z. B. zur Betriebsdauer oder zum aktuellen Status.

Bild

Prozesserstellung: Details



Eines der interessanten Dinge ist, wie genau Programme in Prozesse umgewandelt werden. Insbesondere, wie das Betriebssystem das Programm aufnimmt und ausführt. Wie genau wird der Prozess erstellt?
Zunächst muss das Betriebssystem den Programmcode und die statischen Daten in den Speicher (im Prozessadressraum) laden. Programme befinden sich normalerweise auf einer Festplatte oder in einem Solid-State-Laufwerk in einem ausführbaren Format. Für das Laden eines Programms und statischer Daten in den Speicher muss das Betriebssystem diese Bytes von der Festplatte lesen und irgendwo im Speicher ablegen.

In frühen Betriebssystemen wurde der Startvorgang eifrig ausgeführt, was bedeutet, dass der Code vor dem Start des Programms vollständig in den Speicher geladen wurde. Moderne Betriebssysteme tun dies träge, dh sie laden Code- oder Datenstücke nur dann, wenn sie vom Programm während seiner Ausführung benötigt werden.

Nachdem der Code und die statischen Daten in den Speicher des Betriebssystems geladen wurden, müssen Sie einige weitere Schritte ausführen, bevor Sie den Vorgang starten. Dem Stapel sollte eine bestimmte Speichermenge zugewiesen werden. Programme verwenden den Stapel für lokale Variablen, Funktionsparameter und Rücksprungadressen . Das Betriebssystem weist diesen Speicher zu und gibt ihn dem Prozess. Der Stapel kann auch mit einigen Argumenten zugewiesen werden, insbesondere füllt er die Parameter der Funktion main () mit dem Array argc und argv.

Das Betriebssystem kann auch eine bestimmte Menge an Speicher für den Heap des Programms zuweisen. Der Heap wird von Programmen für explizit angeforderte dynamisch zugewiesene Daten verwendet . Programme fordern diesen Speicherplatz durch Aufrufen der Funktion malloc () an und löschen ihn explizit durch Aufrufen der Funktion free () . Für Datenstrukturen wie verknüpfte Blätter, Hash-Tabellen, Bäume und andere wird ein Heap benötigt. Zunächst wird eine kleine Menge an Speicher unter dem Heap zugewiesen, aber im Laufe der Zeit kann der Heap während des Programmbetriebs über den Bibliotheks-API-Aufruf malloc () mehr Speicher anfordern. Das Betriebssystem ist an der Zuweisung von mehr Speicher beteiligt, um diese Herausforderungen zu bewältigen.

Das Betriebssystem führt auch Initialisierungsaufgaben aus, insbesondere im Zusammenhang mit E / A. Auf UNIX-Systemen verfügt jeder Prozess beispielsweise standardmäßig über 3 offene Dateideskriptoren für Standardeingabe-, Ausgabe- und Fehlerflüsse. Mit diesen Deskriptoren können Programme Eingaben vom Terminal lesen und Informationen auf dem Bildschirm anzeigen.

Durch das Laden des Codes und der statischen Daten in den Speicher, das Erstellen und Initialisieren des Stapels sowie andere Arbeiten im Zusammenhang mit der Ausführung von E / A-Aufgaben bereitet das Betriebssystem den Standort auf den Prozess vor. Am Ende bleibt die letzte Aufgabe: das Programm über seinen Einstiegspunkt auszuführen, der als main () -Funktion bezeichnet wird. Wenn Sie zur Funktion main () übergehen, überträgt das Betriebssystem die CPU-Steuerung an den neu erstellten Prozess, sodass das Programm gestartet wird.

Prozessstatus


Nachdem wir verstanden haben, was ein Prozess ist und wie er erstellt wird, listen wir die Zustände des Prozesses auf, in dem er sein kann. In seiner einfachsten Form kann sich ein Prozess in einem der folgenden Zustände befinden:
Laufen . Im laufenden Zustand läuft der Prozess auf dem Prozessor. Dies bedeutet, dass Anweisungen ausgeführt werden.
Bereit . In einem Bereitschaftszustand ist der Prozess startbereit, aber aus irgendeinem Grund führt das Betriebssystem ihn zu einem bestimmten Zeitpunkt nicht aus.
Blockiert . In einem gesperrten Zustand führt der Prozess einige Vorgänge aus, die verhindern, dass er zur Ausführung bereit ist, bis ein Ereignis eintritt. Ein häufiges Beispiel ist, wenn ein Prozess eine E / A-Operation initiiert, diese blockiert wird und daher ein anderer Prozess den Prozessor verwenden kann.

Bild

Sie können sich diese Zustände in Form eines Diagramms vorstellen. Wie wir auf dem Bild sehen können, kann sich der Status des Prozesses nach Ermessen des Betriebssystems zwischen RUNNING und READY ändern. Wenn sich der Status eines Prozesses von READY in RUNNING ändert, bedeutet dies, dass der Prozess geplant wurde. In die entgegengesetzte Richtung - aus dem Layout entfernt. In dem Moment, in dem der Prozess blockiert wird, z. B. wenn ich eine E / A-Operation initiiere, hält das Betriebssystem ihn in diesem Zustand, bis ein Ereignis eintritt, z. B. der Abschluss der E / A. In diesem Moment wechseln Sie in den Status READY und möglicherweise sofort in den Status RUNNING, wenn das Betriebssystem dies entscheidet.
Schauen wir uns ein Beispiel an, wie zwei Prozesse diese Zustände durchlaufen. Stellen Sie sich zunächst vor, dass beide Prozesse ausgeführt werden und jeder nur die CPU verwendet. In diesem Fall sehen ihre Zustände wie folgt aus.

Bild

Im folgenden Beispiel fordert der erste Prozess nach einer Weile eine E / A an und wechselt in den Status BLOCKED, wodurch der andere Prozess gestartet werden kann (Abb. 1.4). Das Betriebssystem erkennt, dass Prozess 0 die CPU nicht verwendet und startet Prozess 1. Während der Ausführung von Prozess 1 - E / A wird beendet und der Status von Prozess 0 ändert sich in BEREIT. Schließlich ist Prozess 1 abgeschlossen, und am Ende startet, führt und beendet Prozess 0 seine Arbeit.

Bild

Datenstruktur


Das Betriebssystem selbst ist ein Programm und verfügt wie jedes andere Programm über einige wichtige Datenstrukturen, die eine Vielzahl relevanter Informationen verfolgen. Um den Status jedes Prozesses im Betriebssystem zu verfolgen, werden eine bestimmte Prozessliste für alle Prozesse im Status READY und einige zusätzliche Informationen zum Verfolgen der aktuell ausgeführten Prozesse unterstützt. Außerdem muss das Betriebssystem Prozesse verfolgen und blockieren. Nach Abschluss der E / A muss das Betriebssystem den gewünschten Prozess aktivieren und in den Startzustand versetzen.

So muss das Betriebssystem beispielsweise den Status der Prozessorregister speichern. In dem Moment, in dem der Prozess stoppt, wird der Status der Register im Adressraum des Prozesses gespeichert, und zum Zeitpunkt seiner Fortsetzung ist es möglich, die Werte der Register wiederherzustellen und somit den Prozess fortzusetzen.

Zusätzlich zu den bereitgestellten, blockierten und laufenden Zuständen gibt es einige andere Zustände. Manchmal kann ein Prozess zum Zeitpunkt der Erstellung einen INIT-Status haben. Schließlich kann ein Prozess in den Status FINAL versetzt werden, wenn er bereits abgeschlossen ist, die Informationen darüber jedoch noch nicht gelöscht wurden. Auf UNIX-Systemen wird dieser Status als Zombie-Prozess bezeichnet . Dieser Status ist nützlich für Fälle, in denen der übergeordnete Prozess den Rückkehrcode des Nachkommen wissen möchte. Beispielsweise zeigt 0 normalerweise einen erfolgreichen Abschluss und 1 einen Fehler an, aber Programmierer können zusätzliche Ausgabecodes erstellen, die verschiedene Probleme signalisieren. Nach Abschluss führt der übergeordnete Prozess den letzten Systemaufruf aus, z. B. wait (), um auf den Abschluss des untergeordneten Prozesses zu warten und dem Betriebssystem zu signalisieren, dass alle mit dem abgeschlossenen Prozess verknüpften Daten gelöscht werden können.



Kernpunkte der Vorlesung:


Prozess - die Hauptabstraktion eines laufenden Programms im Betriebssystem. Ein Prozess kann jederzeit durch seinen Zustand beschrieben werden: den Inhalt des Speichers in seinem Adressraum, den Inhalt der Prozessorregister, einschließlich des Befehlszeigers und des Stapelzeigers, auch mit Informationen über E / A, beispielsweise geöffnete Dateien, die gelesen oder geschrieben werden.
● Die Prozess-API besteht aus Aufrufen, die Programme in Bezug auf Prozesse ausführen können. Normalerweise sind dies Aufrufe zum Erstellen, Löschen oder für andere.
● Ein Prozess befindet sich in einem von vielen Zuständen, einschließlich Ausführen, Bereit, Blockiert. Verschiedene Ereignisse wie Planung, Ausschluss von der Planung oder Erwartungen können den Status eines Prozesses von einem zum anderen übertragen.
● Die Prozessliste enthält Informationen zu allen Prozessen im System. Jeder Eintrag darin wird als Prozesssteuerungsblock bezeichnet. In Wirklichkeit handelt es sich dabei um eine Struktur, die alle erforderlichen Informationen zu einem bestimmten Prozess enthält.

Source: https://habr.com/ru/post/de446866/


All Articles