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

Einführung in Betriebssysteme

Hey Habr! Ich möchte Sie auf eine Reihe von Artikeln und Übersetzungen einer meiner Meinung nach interessanten Literatur aufmerksam machen – OSTEP. In diesem Material wird ausführlich auf die Arbeit unixähnlicher Betriebssysteme eingegangen, nämlich auf die Arbeit mit Prozessen, verschiedenen Schedulern, Speicher und anderen ähnlichen Komponenten, aus denen ein modernes Betriebssystem besteht. Das Original aller Materialien können Sie hier einsehen hier. Bitte beachten Sie, dass die Übersetzung unprofessionell (ziemlich frei) angefertigt wurde, aber ich hoffe, dass ich die allgemeine Bedeutung beibehalten habe.

Laborarbeiten zu diesem Thema finden Sie hier:

Andere teile:

Sie können auch auf meinem Kanal vorbeischauen Telegramm =)

Schauen wir uns die grundlegendste Abstraktion an, die das Betriebssystem den Benutzern bietet: den Prozess. Die Definition des Prozesses ist recht einfach – das ist sie laufendes Programm. Das Programm selbst ist ein lebloses Ding, das sich auf der Festplatte befindet – es besteht aus einer Reihe von Anweisungen und möglicherweise einigen statischen Daten, die darauf warten, gestartet zu werden. Es ist das Betriebssystem, das diese Bytes übernimmt und ausführt, wodurch das Programm in etwas Nützliches umgewandelt wird.
In den meisten Fällen möchten Benutzer mehr als ein Programm gleichzeitig ausführen. Sie können beispielsweise einen Browser, ein Spiel, einen Mediaplayer, einen Texteditor und dergleichen auf Ihrem Laptop ausführen. Tatsächlich kann ein typisches System Dutzende oder Hunderte von Prozessen gleichzeitig ausführen. Diese Tatsache macht das System benutzerfreundlicher, Sie müssen sich nie darum kümmern, ob die CPU frei ist, sondern können einfach Programme ausführen.

Dies wirft das Problem auf: Wie kann die Illusion vieler CPUs erzeugt werden? Wie kann das Betriebssystem die Illusion einer nahezu unendlichen Anzahl von CPUs erzeugen, selbst wenn Sie nur über eine physische CPU verfügen?

Das Betriebssystem erzeugt diese Illusion durch CPU-Virtualisierung. Indem es einen Prozess startet, ihn dann stoppt, einen anderen Prozess startet usw., kann das Betriebssystem die Illusion aufrechterhalten, dass es viele virtuelle CPUs gibt, obwohl es in Wirklichkeit einen oder mehrere physische Prozessoren gibt. Diese Technik heißt Aufteilung der CPU-Ressourcen nach Zeit. Mit dieser Technik können Benutzer beliebig viele Prozesse gleichzeitig ausführen. Der Preis dieser Lösung liegt in der Leistung – denn wenn die CPU von mehreren Prozessen gemeinsam genutzt wird, wird jeder Prozess langsamer verarbeitet.
Um die CPU-Virtualisierung zu implementieren und vor allem gut zu machen, benötigt das Betriebssystem sowohl Low-Level- als auch High-Level-Unterstützung. Es wird Low-Level-Unterstützung genannt Mechanismen sind Low-Level-Methoden oder Protokolle, die den erforderlichen Teil der Funktionalität implementieren. Ein Beispiel für eine solche Funktionalität ist der Kontextwechsel, der dem Betriebssystem die Möglichkeit gibt, ein Programm zu stoppen und ein anderes Programm auf dem Prozessor auszuführen. Diese Zeiteinteilung ist in allen modernen Betriebssystemen implementiert.
Zusätzlich zu diesen Mechanismen ist eine Logik in Form von „Richtlinien“ in das Betriebssystem integriert. Politik ist ein bestimmter Entscheidungsalgorithmus für das Betriebssystem. Solche Richtlinien entscheiden beispielsweise, welches Programm (aus einer Liste von Befehlen) zuerst gestartet werden soll. So wird dieses Problem beispielsweise durch eine Richtlinie namens gelöst Scheduler (Planungsrichtlinie) и при выборе решения будет руководствоваться такими данными как: история запуска (какая программа была запущена дольше всех за последнюю минут), какую нагрузку осуществляет данный процесс (какие типы программ были запущены), метрики производительности (оптимизирована ли система для интерактивного взаимодействия или для пропускной способности ) usw.

Abstraktion: Prozess

Die Abstraktion eines laufenden Programms, das vom Betriebssystem ausgeführt wird, nennen wir Prozess. Wie bereits erwähnt, ist ein Prozess einfach ein laufendes Programm zu einem beliebigen Zeitpunkt. Ein Programm, mit dem wir zusammenfassende Informationen von verschiedenen Systemressourcen erhalten können, auf die dieses Programm während seiner Ausführung zugreift oder die es beeinflusst.
Um die Komponenten des Prozesses zu verstehen, müssen Sie die Zustände des Systems verstehen: was das Programm während seines Betriebs lesen oder ändern kann. Sie müssen jederzeit verstehen, welche Elemente des Systems für die Ausführung des Programms wichtig sind.
Eines der offensichtlichen Elemente des Systemzustands, den der Prozess umfasst, ist Speicher. Anweisungen befinden sich im Speicher. Die Daten, die das Programm liest oder schreibt, befinden sich ebenfalls im Speicher. Somit ist der Speicher, den ein Prozess adressieren kann (Adressraum genannt), Teil des Prozesses.
Zum Systemzustand gehören auch Register. Viele Anweisungen zielen darauf ab, den Wert von Registern zu ändern oder ihren Wert zu lesen, und daher werden Register auch zu einem wichtigen Teil des Prozessablaufs.
Es ist zu beachten, dass der Maschinenzustand auch aus einigen speziellen Registern gebildet wird. Zum Beispiel, IP – Anweisungszeiger – ein Zeiger auf die Anweisung, die das Programm gerade ausführt. Es gibt noch Stapelzeiger und damit verbunden Rahmenzeiger, die zur Verwaltung von Funktionsparametern, lokalen Variablen und Rücksprungadressen verwendet werden.
Schließlich greifen Programme häufig auf ROM (Nur-Lese-Speicher) zu. Diese „E/A“-Informationen (Eingabe/Ausgabe) sollten eine Liste der Dateien enthalten, die derzeit vom Prozess geöffnet sind.

Prozess-API

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

Erstellen (Erstellung): Das Betriebssystem muss eine Methode enthalten, mit der Sie neue Prozesse erstellen können. Wenn Sie einen Befehl in das Terminal eingeben oder eine Anwendung durch Doppelklick auf ein Symbol starten, wird ein Aufruf an das Betriebssystem gesendet, einen neuen Prozess zu erstellen und dann das angegebene Programm zu starten.
Entfernung: Da es eine Schnittstelle zum Erstellen eines Prozesses gibt, sollte das Betriebssystem auch die Möglichkeit bieten, das Entfernen eines Prozesses zu erzwingen. Die meisten Programme starten und beenden sich während der Ausführung automatisch. Andernfalls möchte der Benutzer sie beenden können und daher wäre eine Schnittstelle zum Stoppen des Prozesses nützlich.
Wartezeit (Warten): Manchmal ist es nützlich, auf den Abschluss eines Prozesses zu warten. Daher werden einige Schnittstellen bereitgestellt, die die Möglichkeit zum Warten bieten.
Sonstige Kontrolle (verschiedene Kontrollen): Neben dem Töten und Warten auf den Prozess gibt es auch verschiedene andere Kontrollmethoden. Beispielsweise bieten die meisten Betriebssysteme die Möglichkeit, einen Prozess einzufrieren (seine Ausführung für einen bestimmten Zeitraum anzuhalten) und ihn dann fortzusetzen (seine Ausführung fortzusetzen).
Status (Zustand): Es gibt verschiedene Schnittstellen, um Informationen über den Status eines Prozesses zu erhalten, z. B. wie lange er ausgeführt wurde oder in welchem ​​Zustand er sich gerade befindet.

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

Prozesserstellung: Details

Interessant ist vor allem, wie genau Programme in Prozesse umgewandelt werden. Insbesondere wie das Betriebssystem das Programm aufnimmt und ausführt. Wie genau der Prozess entsteht.
Zunächst muss das Betriebssystem den Programmcode und die statischen Daten in den Speicher (in den Prozessadressraum) laden. Programme befinden sich normalerweise in einem ausführbaren Format auf einer Festplatte oder einem Solid-State-Laufwerk. Daher erfordert der Prozess des Ladens von Programm- und statischen Daten in den Speicher, dass das Betriebssystem in der Lage ist, diese Bytes von der Festplatte zu lesen und sie irgendwo im Speicher abzulegen.

In frühen Betriebssystemen erfolgte der Ladevorgang schnell, was bedeutete, dass der gesamte Code vor dem Start des Programms in den Speicher geladen wurde. Moderne Betriebssysteme tun dies träge, das heißt, sie laden Teile von Code oder Daten nur dann, wenn das Programm sie während seiner Ausführung benötigt.

Sobald der Code und die statischen Daten in den Betriebssystemspeicher geladen sind, müssen noch einige weitere Dinge erledigt werden, bevor der Prozess ausgeführt werden kann. Dem Stapel muss eine gewisse Speichermenge zugewiesen werden. Programme nutzen den Stack für lokale Variablen, Funktionsparameter und Rücksprungadressen. Das Betriebssystem weist diesen Speicher zu und gibt ihn an den Prozess weiter. Der Stapel kann auch mit einigen Argumenten belegt werden, insbesondere füllt er die Parameter der Funktion main(), beispielsweise mit einem Array aus argc und argv.

Das Betriebssystem weist dem Programm-Heap möglicherweise auch etwas Speicher zu. Der Heap wird von Programmen verwendet, um dynamisch zugewiesene Daten explizit anzufordern. Programme fordern diesen Platz an, indem sie die Funktion aufrufen malloc () und löscht es explizit durch Aufruf der Funktion kostenlos(). Der Heap wird für Datenstrukturen wie verknüpfte Blätter, Hashtabellen, Bäume und andere benötigt. Zunächst wird dem Heap eine kleine Menge Speicher zugewiesen, aber im Laufe der Zeit, während das Programm ausgeführt wird, kann der Heap über den Bibliotheks-API-Aufruf malloc() mehr Speicher anfordern. Das Betriebssystem ist an der Zuweisung von mehr Speicher beteiligt, um diese Aufrufe zu erfüllen.

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

Indem das Betriebssystem Code und statische Daten in den Speicher lädt, den Stapel erstellt und initialisiert und andere Arbeiten im Zusammenhang mit der Ausführung von E/A-Aufgaben erledigt, bereitet es die Bühne für die Ausführung des Prozesses vor. Schließlich bleibt noch eine letzte Aufgabe übrig: das Ausführen des Programms über seinen Einstiegspunkt, die sogenannte main()-Funktion. Durch die Ausführung der Funktion main() übergibt das Betriebssystem die CPU-Steuerung an den neu erstellten Prozess, sodass das Programm mit der Ausführung beginnt.

Prozessstatus

Nachdem wir nun ein wenig verstanden haben, was ein Prozess ist und wie er erstellt wird, wollen wir die Prozesszustände auflisten, in denen er sich befinden kann. In seiner einfachsten Form kann sich ein Prozess in einem dieser Zustände befinden:
Laufen. Beim Ausführen läuft der Prozess auf dem Prozessor. Das bedeutet, dass Anweisungen ausgeführt werden.
Bereit. Im Bereitschaftszustand ist der Prozess zur Ausführung bereit, das Betriebssystem führt ihn jedoch aus irgendeinem Grund nicht zum angegebenen Zeitpunkt aus.
Gesperrt. Im blockierten Zustand führt ein Prozess einige Vorgänge aus, die verhindern, dass er zur Ausführung bereit ist, bis ein Ereignis eintritt. Ein häufiges Beispiel ist, dass ein Prozess, der einen E/A-Vorgang initiiert, blockiert wird, sodass ein anderer Prozess den Prozessor verwenden kann.

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

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

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

Im folgenden Beispiel fordert der erste Prozess nach einiger Zeit E/A an und wechselt in den Status BLOCKED, wodurch ein anderer Prozess ausgeführt werden kann (Abb. 1.4). Das Betriebssystem erkennt, dass Prozess 0 die CPU nicht nutzt und startet Prozess 1. Während Prozess 1 ausgeführt wird, ist IO abgeschlossen und der Status von Prozess 0 ändert sich in READY. Schließlich ist Prozess 1 abgeschlossen und nach Abschluss startet Prozess 0 seine Arbeit, führt sie aus und beendet sie.

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

Datenstruktur

Das Betriebssystem selbst ist ein Programm und verfügt wie jedes andere Programm über einige wichtige Datenstrukturen, die verschiedene relevante Informationen verfolgen. Um den Status jedes Prozesses zu verfolgen, unterstützt das Betriebssystem einige Prozessliste für alle Prozesse im READY-Status und einige zusätzliche Informationen zur Verfolgung aktuell laufender Prozesse. Außerdem sollte das Betriebssystem blockierte Prozesse überwachen. Nachdem IO abgeschlossen ist, muss das Betriebssystem den erforderlichen Prozess aktivieren und in einen laufbereiten Zustand versetzen.

Beispielsweise muss das Betriebssystem den Zustand der Prozessorregister bewahren. In dem Moment, in dem der Prozess stoppt, wird der Zustand der Register im Adressraum des Prozesses gespeichert, und in dem Moment, in dem sein Betrieb fortgesetzt wird, werden die Werte der Register wiederhergestellt und somit wird die Ausführung dieses Prozesses fortgesetzt.

Neben den Zuständen „Bereit“, „Blockiert“ und „Laufen“ gibt es noch einige andere Zustände. Manchmal befindet sich ein Prozess zum Zeitpunkt der Erstellung im INIT-Status. Schließlich kann ein Prozess in den FINAL-Zustand versetzt werden, wenn er bereits abgeschlossen ist, seine Informationen jedoch noch nicht gelöscht wurden. Auf UNIX-Systemen wird dieser Zustand aufgerufen Zombie-Prozess. Dieser Status ist nützlich für Fälle, in denen ein übergeordneter Prozess den Rückkehrcode eines untergeordneten Prozesses wissen möchte. Normalerweise signalisiert 0 beispielsweise einen Erfolg und 1 einen Fehler, aber Programmierer können zusätzliche Ausgabecodes ausgeben, um andere Probleme zu signalisieren. Wenn der übergeordnete Prozess beendet wird, führt er einen letzten Systemaufruf durch, z. B. wait(), um auf die Beendigung des untergeordneten Prozesses zu warten und dem Betriebssystem zu signalisieren, dass es alle mit dem beendeten Prozess verbundenen Daten löschen kann.

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

Kernpunkte der Vorlesung:

Prozess — die Hauptabstraktion eines laufenden Programms im Betriebssystem. Zu jedem Zeitpunkt kann ein Prozess durch seinen Zustand beschrieben werden: den Inhalt des Speichers in seinem Adressraum, den Inhalt der Prozessorregister, einschließlich Befehlszeiger und Stapelzeiger, sowie E/A-Informationen, wie z. B. geöffnete Dateien, die gelesen oder geschrieben werden.
Prozess-API besteht aus Aufrufen, die Programme an Prozesse durchführen können. Typischerweise handelt es sich dabei um Aufrufe zum Erstellen, Löschen oder andere Aufrufe.
● Der Prozess befindet sich in einem von vielen Status, einschließlich läuft, bereit, blockiert. Verschiedene Ereignisse wie Planung, Ausnahmen von der Planung oder Wartezeiten können den Status eines Prozesses von einem zum anderen ändern.
Prozessliste enthält Informationen über alle Prozesse im System. Jeder darin enthaltene Eintrag wird als Prozesskontrollblock bezeichnet. Dabei handelt es sich in Wirklichkeit um eine Struktur, die alle notwendigen Informationen zu einem bestimmten Prozess enthält. 

Source: habr.com

Kommentar hinzufügen