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

EinfĂŒhrung in Betriebssysteme

Hallo, Habr! Ich möchte Ihnen eine Serie von Übersetzungen einer interessanten Literatur — OSTEP — vorstellen. In diesem Material wird die Funktionsweise von Unix-Ă€hnlichen Betriebssystemen ziemlich grĂŒndlich behandelt, insbesondere die Arbeit mit Prozessen, verschiedenen Planern, Speicher und anderen Ă€hnlichen Komponenten, die ein modernes Betriebssystem ausmachen. Das Original aller Materialien können Sie hier ansehen hier. Bitte beachten Sie, dass die Übersetzung unprofessionell (relativ frei) durchgefĂŒhrt wurde, aber ich hoffe, dass ich den allgemeinen Sinn bewahrt habe.

Die Laborarbeiten zu diesem Thema finden Sie hier:

Andere Teile:

Und Sie können auch meinen Kanal auf Telegramm =)

Schauen wir uns die grundlegendste Abstraktion an, die das Betriebssystem den Benutzern bietet: den Prozess. Die Definition eines Prozesses ist recht einfach — es ist eine ausgefĂŒhrte Programm. Ein Programm an sich ist eine lebloses Ding, das sich auf der Festplatte befindet — es ist ein Satz von Anweisungen und möglicherweise einigen statischen Daten, die darauf warten, gestartet zu werden. Es ist das Betriebssystem, das diese Bytes nimmt und sie ausfĂŒhrt, wobei es das Programm in etwas NĂŒtzliches verwandelt.
HĂ€ufig möchten Benutzer mehr als ein Programm gleichzeitig ausfĂŒhren, beispielsweise können Sie auf Ihrem Laptop einen Browser, ein Spiel, einen Media Player, einen Texteditor und Ähnliches starten. TatsĂ€chlich kann ein typisches System Dutzende und Hunderte von Prozessen gleichzeitig ausfĂŒhren. Diese Tatsache macht das System benutzerfreundlicher, man muss sich nie sorgen, ob die CPU frei ist, man startet einfach Programme.

Hieraus ergibt sich das Problem: Wie schafft man die Illusion vieler CPUs? Wie kann das Betriebssystem die Illusion praktischerweise unzÀhliger CPUs erzeugen, auch wenn man nur einen physischen CPU hat?

Das Betriebssystem erzeugt diese Illusion durch die Virtualisierung der CPU. Indem es einen Prozess startet, ihn dann stoppt, einen anderen Prozess startet und so weiter, kann das Betriebssystem die Illusion aufrechterhalten, dass es viele virtuelle CPUs gibt, obwohl es sich tatsĂ€chlich um einen oder mehrere physische Prozessoren handelt. Diese Technik wird genannt CPU-Ressourcenteilung nach Zeit. Diese Technik erlaubt es Benutzern, so viele gleichzeitige Prozesse auszufĂŒhren, wie sie möchten. Der Preis fĂŒr diese Lösung ist die Leistung – da, wenn die CPU von mehreren Prozessen geteilt wird, jeder Prozess langsamer bearbeitet wird.
FĂŒr die Umsetzung der CPU-Virtualisierung, insbesondere um dies gut zu tun, benötigt das Betriebssystem sowohl niedrige als auch hohe UnterstĂŒtzung. NiedriglevelunterstĂŒtzung – das sind niedriglevel Methoden oder Protokolle, die den erforderlichen Funktionsbereich implementieren. Ein Beispiel fĂŒr eine solche FunktionalitĂ€t ist das Kontextwechseln, das dem Betriebssystem ermöglicht, ein Programm anzuhalten und ein anderes auf der CPU zu starten. Diese zeitliche Teilung ist in allen modernen Betriebssystemen implementiert.
Oben auf diesen Mechanismen liegt eine gewisse Logik, die im Betriebssystem in Form von „Politiken“ angelegt ist. Politik – das ist ein Algorithmus zur Entscheidungsfindung des Betriebssystems. Solche Politiken entscheiden beispielsweise, welches Programm (aus der Befehlsliste) zuerst gestartet werden soll. So wird beispielsweise diese Aufgabe durch eine Politik gelöst, die als Planungspolitik (scheduling policy) bezeichnet wird und bei der Auswahl der Lösung auf Daten wie folgt zurĂŒckgreift: Laufhistorie (welches Programm am lĂ€ngsten in der letzten Minute ausgefĂŒhrt wurde), welche Last dieser Prozess verursacht (welche Programmarten ausgefĂŒhrt wurden), Leistungsmetriken (ob das System fĂŒr interaktive Interaktion oder fĂŒr Durchsatz optimiert ist) usw.

Abstraktion: Prozess

Die Abstraktion eines laufenden Programms, das vom Betriebssystem ausgefĂŒhrt wird, ist das, was wir Prozessnennen. Wie bereits frĂŒher erwĂ€hnt, ist ein Prozess einfach ein laufendes Programm zu jedem Zeitpunkt. Ein Programm, mithilfe dessen wir zusammenfassende Informationen von verschiedenen Systemressourcen abrufen können und auf die diese Programme wĂ€hrend ihrer AusfĂŒhrung zugreifen oder die sie betreffen.
Um die Bestandteile eines Prozesses zu verstehen, muss man die ZustĂ€nde des Systems verstehen: was das Programm wĂ€hrend seiner AusfĂŒhrung lesen oder Ă€ndern kann. Zu jedem Zeitpunkt muss man verstehen, welche Elemente des Systems fĂŒr die AusfĂŒhrung des Programms wichtig sind.
Eines der offensichtlichen Elemente des Systemzustands, das den Prozess umfasst, ist der Speicher. Die Anweisungen befinden sich im Speicher. Die Daten, die das Programm liest oder schreibt, werden ebenfalls im Speicher gespeichert. Daher ist der Speicher, den der Prozess adressieren kann (der sogenannte Adressraum), Teil des Prozesses.
Auch die Register sind Teil des Systemzustands. Viele Anweisungen zielen darauf ab, den Wert von Registern zu Àndern oder ihren Wert zu lesen, und somit werden die Register ebenfalls zu einem wichtigen Teil der Arbeitsweise des Prozesses.
Es ist zu beachten, dass der Maschinenzustand auch aus bestimmten speziellen Registern besteht. Zum Beispiel IP — der Befehlszeiger — ist der Zeiger auf den Befehl, den das Programm gerade ausfĂŒhrt. Es gibt auch einen Stackzeiger und den dazugehörigen Rahmenzeiger, die zur Verwaltung von Funktionen, lokalen Variablen und RĂŒcksprungadressen verwendet werden.
Schließlich greifen Programme hĂ€ufig auf den ROM (nichtflĂŒchtiger Speicher) zu. Diese Informationen ĂŒber "I/O" (Eingabe/Ausgabe) sollten eine Liste von Dateien enthalten, die der Prozess gerade geöffnet hat.

Process API

Um das VerstĂ€ndnis der Arbeitsweise eines Prozesses zu verbessern, betrachten wir Beispiele fĂŒr Systemaufrufe, die in jedes Betriebssystem-Interface integriert werden sollten. Diese APIs sind in irgendeiner Form auf jedem OS verfĂŒgbar.

● Erstellen (Erstellung): Das Betriebssystem muss eine Methode zur VerfĂŒgung stellen, um neue Prozesse zu erstellen. Wenn Sie einen Befehl im Terminal eingeben oder eine Anwendung durch Doppelklick auf das Symbol starten, wird eine Anfrage an das Betriebssystem gesendet, um einen neuen Prozess zu erstellen und das angegebene Programm zu starten.
● Löschen: Da es eine Schnittstelle zur Erstellung von Prozessen gibt, muss das Betriebssystem auch die Möglichkeit bieten, Prozesse gewaltsam zu löschen. Die meisten Programme werden sich natĂŒrlich selbst starten und beenden, wĂ€hrend sie ausgefĂŒhrt werden. Andernfalls möchte der Benutzer in der Lage sein, sie zu beenden, und somit wĂ€re eine Schnittstelle zum Stoppen von Prozessen nicht ĂŒberflĂŒssig.
● Warten (Warten): Manchmal ist es nĂŒtzlich, auf die Beendigung eines Prozesses zu warten, daher werden einige Schnittstellen bereitgestellt, die die Möglichkeit des Wartens bieten.
● Sonstige Steuerung (verschiedene Steuerung): Neben dem Töten und Warten auf den Prozess gibt es noch andere verschiedene Kontrollmethoden. Zum Beispiel bieten die meisten Betriebssysteme die Möglichkeit, einen Prozess einzufrieren (seine AusfĂŒhrung fĂŒr eine gewisse Zeit zu stoppen) und anschließend fortzusetzen (die AusfĂŒhrung wieder aufzunehmen).
● Status (zustand): Es gibt verschiedene Schnittstellen, um Informationen ĂŒber den Status des Prozesses zu erhalten, wie die Dauer seiner AusfĂŒhrung oder in welchem Zustand er sich gerade befindet.

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

Prozess erstellen: Details

Eine der interessanten Dinge ist, wie Programme genau in Prozesse umgewandelt werden. Insbesondere, wie das Betriebssystem ein Programm lÀdt und startet. Wie genau ein Prozess erstellt wird.
ZunĂ€chst muss das Betriebssystem den Programmcode und die statischen Daten in den Arbeitsspeicher (in den Adressraum des Prozesses) laden. Programme sind normalerweise auf einer Festplatte oder einem SSD in einem bestimmten ausfĂŒhrbaren Format gespeichert. Daher erfordert der Prozess des Ladens des Programmcodes und der statischen Daten in den Speicher vom Betriebssystem die FĂ€higkeit, diese Bytes von der Festplatte zu lesen und sie irgendwo im Speicher zu platzieren.

In frĂŒhen Betriebssystemen wurde der Ladeprozess ungeduldig (eagerly) durchgefĂŒhrt, was bedeutet, dass der Code vollstĂ€ndig in den Speicher geladen wurde, bevor das Programm gestartet wurde. Moderne Betriebssysteme tun dies faul (lazily), indem sie Teile des Codes oder der Daten nur dann laden, wenn sie wĂ€hrend der ProgrammausfĂŒhrung benötigt werden.

Nachdem der Code und die statischen Daten in den Speicher geladen sind, muss das Betriebssystem noch einige Dinge erledigen, bevor der Prozess gestartet wird. Ein gewisser Teil des Speichers muss fĂŒr den Stack reserviert werden. Programme verwenden den Stack fĂŒr lokale Variablen, Funktionparameter und RĂŒcksprungadressen.. Das Betriebssystem weist diesen Speicher zu und gibt ihn dem Prozess. Der Stack kann auch mit bestimmten Argumenten reserviert werden, speziell fĂŒllt er die Parameter der Funktion main(), beispielsweise mit dem Array argc und argv.

Das Betriebssystem kann auch einen bestimmten Teil des Speichers fĂŒr den Heap des Programms reservieren. Der Heap wird von Programmen fĂŒr ausdrĂŒcklich angeforderte dynamisch zugewiesene Daten verwendet.. Programme beantragen diesen Speicher mit dem Aufruf der Funktion malloc() und geben ihn ausdrĂŒcklich frei, indem sie die Funktion free(). Der Heap ist fĂŒr Datenstrukturen wie: verkettete Listen, Hash-Tabellen, BĂ€ume und andere erforderlich. ZunĂ€chst wird ein kleines StĂŒck Speicher fĂŒr den Heap reserviert, aber im Laufe der ProgrammausfĂŒhrung kann der Heap ĂŒber die bibliotheksseitige API-Funktion malloc() mehr Speicher anfordern. Das Betriebssystem ist in den Prozess der Zuweisung zusĂ€tzlichen Speichers eingebunden, um diesen Anforderungen nachzukommen.

Das Betriebssystem wird auch Initialisierungsaufgaben ausfĂŒhren, insbesondere solche, die mit Ein- und Ausgabe zu tun haben. In UNIX-Systemen hat jeder Prozess standardmĂ€ĂŸig 3 geöffnete Dateideskriptoren fĂŒr den Standard-Eingangs-, Ausgangs- und Fehlerstrom. Diese Deskriptoren ermöglichen es Programmen, Eingaben vom Terminal zu lesen und Informationen auf dem Bildschirm auszugeben.

So bereitet das Betriebssystem den Raum fĂŒr die AusfĂŒhrung eines Prozesses vor, indem es Code und statische Daten in den Speicher lĂ€dt, einen Stapel erstellt und initialisiert sowie andere Aufgaben im Zusammenhang mit der DurchfĂŒhrung von Ein- und Ausgaben ausfĂŒhrt. Schließlich bleibt die letzte Aufgabe: das Programm ĂŒber seinen Einstiegspunkt, die Funktion main(), zur AusfĂŒhrung zu bringen. Wenn die AusfĂŒhrung der Funktion main() ĂŒbergeben wird, ĂŒbergibt das Betriebssystem die Kontrolle an die neu erstellte Prozessinstanz, wodurch das Programm ausgefĂŒhrt wird.

Zustand des Prozesses

Jetzt, da wir ein gewisses VerstÀndnis davon haben, was ein Prozess ist und wie er erstellt wird, lassen Sie uns die ZustÀnde des Prozesses auflisten, in denen er sich befinden kann. In seiner einfachsten Form kann sich ein Prozess in einem dieser ZustÀnde befinden:
● Laufend. Im laufenden Zustand wird der Prozess vom Prozessor ausgefĂŒhrt. Das bedeutet, dass Anweisungen ausgefĂŒhrt werden.
● Bereit. Im bereiten Zustand ist der Prozess bereit zur AusfĂŒhrung, aber aus bestimmten GrĂŒnden wird er im gegebenen Moment nicht vom Betriebssystem ausgefĂŒhrt.
● Blockiert. Im blockierten Zustand fĂŒhrt der Prozess bestimmte Operationen aus, die es ihm nicht ermöglichen, bereit zur AusfĂŒhrung zu sein, bis ein bestimmtes Ereignis eintritt. Ein hĂ€ufiges Beispiel ist, wenn der Prozess eine IO-Operation initialisiert, wird er blockiert, sodass ein anderer Prozess den Prozessor nutzen kann.

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

Man kann sich diese ZustĂ€nde als Graf vorstellen. Wie auf dem Bild zu sehen ist, kann der Zustand eines Prozesses zwischen RUNNING und READY nach Ermessen des Betriebssystems wechseln. Wenn der Zustand eines Prozesses von READY nach RUNNING wechselt, bedeutet das, dass der Prozess geplant wurde. Umgekehrt wird er von der Planung entfernt. In dem Moment, in dem ein Prozess BLOCKED wird, zum Beispiel wenn eine IO-Operation initiiert wird, wird das Betriebssystem ihn in diesem Zustand halten, bis ein Ereignis eintritt, beispielsweise das Ende der IO. In diesem Moment wechselt der Prozess zurĂŒck in den Zustand READY und möglicherweise sofort in den Zustand RUNNING, wenn das das Betriebssystem entscheidet.
Lassen Sie uns ein Beispiel anschauen, wie zwei Prozesse durch diese ZustĂ€nde gehen. ZunĂ€chst nehmen wir an, dass beide Prozesse gestartet sind und jeder nur die CPU nutzt. In diesem Fall wĂŒrden ihre ZustĂ€nde wie folgt aussehen.

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

Im nĂ€chsten Beispiel fordert der erste Prozess nach einer gewissen Zeit der AusfĂŒhrung IO an und wechselt in den Zustand BLOCKED, wodurch dem anderen Prozess die Möglichkeit gegeben wird, zu starten (ABB. 1.4). Das Betriebssystem sieht, dass Prozess 0 die CPU nicht nutzt, und startet Prozess 1. WĂ€hrend der AusfĂŒhrung von Prozess 1 wird das IO abgeschlossen und der Status von Prozess 0 Ă€ndert sich in READY. Schließlich ist Prozess 1 abgeschlossen, und nach dessen Abschluss wird Prozess 0 gestartet, ausgefĂŒhrt und endet seine Arbeit.

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

Datenstruktur

Das Betriebssystem selbst ist ein Programm und hat wie jedes andere Programm einige wichtige Datenstrukturen, die verschiedene relevante Informationen verfolgen. Um den Zustand jedes Prozesses zu verfolgen, wird das Betriebssystem eine gewisse Prozessliste fĂŒr alle Prozesse im Zustand READY und einige zusĂ€tzliche Informationen zur Verfolgung von Prozessen, die gerade laufen, fĂŒhren. Zudem muss das Betriebssystem auch blockierte Prozesse ĂŒberwachen. Nach Abschluss der IO ist das Betriebssystem verpflichtet, den entsprechenden Prozess zu wecken und ihn in den Zustand der Bereitschaft zu versetzen.

So muss das Betriebssystem beispielsweise den Zustand der CPU-Register speichern. Im Moment der Beendigung eines Prozesses wird der Zustand der Register im Adressraum des Prozesses gespeichert und beim Fortsetzen seiner AusfĂŒhrung – die Werte der Register wiederhergestellt, um so die AusfĂŒhrung dieses Prozesses fortzusetzen.

Neben den ZustĂ€nden ready, blocked und running gibt es noch einige andere ZustĂ€nde. Manchmal kann ein Prozess im Moment seiner Erstellung den Zustand INIT haben. Schließlich kann ein Prozess in den Zustand FINAL versetzt werden, wenn er bereits beendet ist, aber die Informationen ĂŒber ihn noch nicht bereinigt wurden. In UNIX-Systemen wird dieser Zustand genannt Zombie-Prozess. Dieser Zustand ist nĂŒtzlich, wenn der Elternprozess den RĂŒckgabecode des Kindes erfahren möchte, zum Beispiel signalisiert in der Regel 0 einen erfolgreichen Abschluss und 1 einen Fehler, jedoch können Programmierer zusĂ€tzliche RĂŒckgabecodes erstellen, um verschiedene Probleme anzuzeigen. Beim Abschluss fĂŒhrt der Elternprozess den letzten Systemaufruf, wie wait(), aus, um auf die Beendigung des Kinderprozesses zu warten und das Betriebssystem darĂŒber zu informieren, dass alle mit dem abgeschlossenen Prozess verbundenen Daten bereinigt werden können.

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

SchlĂŒsselpunkte der Vorlesung:

● Prozess — die Hauptabstraktion eines laufenden Programms im Betriebssystem. Zu jedem Zeitpunkt kann ein Prozess durch seinen Zustand beschrieben werden: der Inhalt des Speichers in seinem Adressraum, der Inhalt der Prozessorregister, einschließlich des Instruction Pointers und des Stack Pointers, sowie Informationen ĂŒber IO, wie beispielsweise geöffnete Dateien, die gelesen oder geschrieben werden.
● Process API besteht aus Aufrufen, die Programme in Bezug auf Prozesse machen können. Normalerweise handelt es sich um Aufrufe zum Erstellen, Löschen oder andere.
● Der Prozess befindet sich in einem der vielen ZustĂ€nde, einschließlich running, ready, blocked. Verschiedene Ereignisse, wie z.B. das Scheduling, die Ausnahme vom Scheduling oder das Warten, können den Zustand eines Prozesses von einem in einen anderen ĂŒberfĂŒhren.
● Prozessliste enthĂ€lt Informationen ĂŒber alle Prozesse im System. Jeder Eintrag darin wird als Prozesskontrollblock bezeichnet, der tatsĂ€chlich eine Struktur darstellt, die alle notwendigen Informationen ĂŒber einen bestimmten Prozess enthĂ€lt. 

Quelle: habr.com

ZuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz kaufen, VPS VDS Server đŸ”„ ZuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz kaufen, VPS VDS Server - ProHoster