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 =)
Programmarbeit
Was passiert, wenn ein Programm funktioniert? Das Ausführen von Programmen macht eine einfache Sache - es führt Anweisungen aus. Jede Sekunde werden vom Prozessor Millionen und möglicherweise Milliarden von Anweisungen aus dem RAM extrahiert, diese wiederum decodiert (z. B. erkennt, zu welchem Typ diese Anweisungen gehören) und ausgeführt. Dies kann das Hinzufügen von zwei Nummern, der Zugriff auf den Speicher, das Überprüfen der Bedingungen, das Umschalten auf Funktionen usw. sein. Nach Abschluss eines Befehls führt der Prozessor einen anderen aus. Und so werden sie Befehl für Befehl ausgeführt, bis das Programm abgeschlossen ist.
Dieses Beispiel wird natürlich als vereinfacht angesehen. Um den Prozessor zu beschleunigen, können Sie mit moderner Hardware Anweisungen außerhalb der Reihe ausführen, mögliche Ergebnisse berechnen, Anweisungen gleichzeitig befolgen und ähnliche Tricks anwenden.
Von Neumann-Rechenmodell
Die von uns beschriebene vereinfachte Arbeitsform ähnelt dem Von-Neumann-Berechnungsmodell.
Von Neumann ist einer der Pioniere der Computersysteme und einer der Autoren der Spieltheorie . Während das Programm ausgeführt wird, treten eine Reihe anderer Ereignisse auf, viele andere Prozesse und Logikfunktionen von Drittanbietern, deren Hauptzweck darin besteht, den Start, den Betrieb und die Wartung des Systems zu vereinfachen.
Es gibt eine Reihe von Software, die für die Einfachheit der Ausführung von Programmen verantwortlich ist (oder sogar das gleichzeitige Ausführen mehrerer Programme ermöglicht). Sie ermöglicht es Programmen, denselben Speicher gemeinsam zu nutzen und mit verschiedenen Geräten zu interagieren. Ein solcher Satz von Software (Software) wird im Wesentlichen als Betriebssystem bezeichnet. Zu seinen Aufgaben gehört die Überwachung der ordnungsgemäßen und effizienten Funktionsweise des Systems sowie die Gewährleistung einer einfachen Verwaltung dieses Systems.
Operationssystem
Ein Betriebssystem, kurz für OS, ist ein Komplex miteinander verbundener Programme, mit denen Computerressourcen verwaltet und die Interaktion eines Benutzers mit einem Computer organisiert werden können .
Das Betriebssystem erreicht seine Wirksamkeit hauptsächlich durch die wichtigste Technik - die
Virtualisierungstechnik . Das Betriebssystem interagiert mit einer physischen Ressource (Prozessor, Speicher, Festplatte usw.) und wandelt sie in eine allgemeinere, leistungsfähigere und benutzerfreundlichere Form um. Für ein allgemeines Verständnis können Sie das Betriebssystem daher sehr grob mit einer virtuellen Maschine vergleichen.
Damit Benutzer dem Betriebssystem Anweisungen geben und damit die Funktionen einer virtuellen Maschine nutzen können (z. B. Starten eines Programms, Zuweisen von Speicher, Zugreifen auf eine Datei usw.), stellt das Betriebssystem eine Schnittstelle bereit, die als
API (Application Programming Interface) bezeichnet wird Sie können Anrufe tätigen. Ein typisches Betriebssystem ermöglicht Hunderte von Systemaufrufen.
Und schließlich, da durch die Virtualisierung viele Programme arbeiten können (wodurch die CPU gemeinsam genutzt wird) und gleichzeitig Zugriff auf ihre Anweisungen und Daten erhalten (wodurch der Speicher gemeinsam genutzt wird) sowie auf Festplatten zugegriffen werden können (wodurch E / A-Geräte gemeinsam genutzt werden) ) wird das Betriebssystem auch als Ressourcenmanager bezeichnet. Jeder Prozessor, jede Festplatte und jeder Speicher ist eine Ressource des Systems, und daher wird eine der Rollen des Betriebssystems zur Aufgabe, diese Ressourcen effizient, ehrlich oder umgekehrt zu verwalten, je nachdem, für welche Aufgabe dieses Betriebssystem ausgelegt ist.
CPU-Virtualisierung
Betrachten Sie das folgende Programm:
(https://www.youtube.com/watch?v=zDwT5fUcki4)

Es werden keine speziellen Aktionen ausgeführt. Tatsächlich wird lediglich die Funktion
spin () aufgerufen, deren Aufgabe es ist, die Zeit zu durchlaufen und nach Ablauf einer Sekunde zurückzukehren. Somit wird die Zeichenfolge, die der Benutzer als Argument übergeben hat, endlos wiederholt.
Führen Sie dieses Programm aus und übergeben Sie ihm das Symbol "A" als Argument. Das Ergebnis ist nicht sehr interessant - das System führt einfach ein Programm aus, das regelmäßig das Symbol „A“ anzeigt.
Versuchen wir nun die Option, wenn viele Instanzen desselben Programms ausgeführt werden, aber unterschiedliche Buchstaben anzeigen, damit es verständlicher wird. In diesem Fall ist das Ergebnis etwas anders. Trotz der Tatsache, dass wir einen Prozessor haben, läuft das Programm gleichzeitig. Wie passiert das? Es stellt sich jedoch heraus, dass das Betriebssystem nicht ohne die Hilfe von Hardwarefunktionen eine Illusion erzeugt. Die Illusion, dass es mehrere virtuelle Prozessoren im System gibt, die einen physischen Prozessor in eine theoretisch unendliche Zahl verwandeln und dadurch ermöglichen, dass Programme gleichzeitig ausgeführt werden. Eine solche Illusion nennt man
CPU-Virtualisierung .
Ein solches Bild wirft viele Fragen auf, zum Beispiel, wenn mehrere Programme gleichzeitig starten möchten, welches wird gestartet? Die "Richtlinien" des Betriebssystems sind für diese Frage verantwortlich. Richtlinien werden an vielen Stellen des Betriebssystems verwendet und beantworten ähnliche Fragen. Sie sind auch die grundlegenden Mechanismen, die das Betriebssystem implementiert. Daher die Rolle des Betriebssystems als Ressourcenmanager.
Speichervirtualisierung
Nun schauen wir uns die Erinnerung an.
Das physikalische Speichermodell in modernen Systemen wird als Array von Bytes dargestellt . Um aus dem Speicher zu lesen, müssen Sie die
Adresse der Zelle angeben, um darauf zugreifen zu können. Um Daten aufzuzeichnen oder zu aktualisieren, müssen Sie auch die Daten und die Adresse der Zelle angeben, in die sie geschrieben werden sollen.
Speicherzugriffe erfolgen während des Programmbetriebs ständig. Ein Programm speichert seine gesamte Datenstruktur im Speicher und greift durch Befolgen verschiedener Anweisungen darauf zu. In der Zwischenzeit werden auch Anweisungen im Speicher gespeichert, sodass bei jeder Anforderung auf die nächste Anweisung zugegriffen werden kann.
Rufen Sie malloc () auf
Betrachten Sie das folgende Programm, das mithilfe des Aufrufs
malloc () (https://youtu.be/jnlKRnoT1m0) einen Speicherbereich
zuweist :

Das Programm macht ein paar Dinge. Zunächst wird eine bestimmte Speichermenge zugewiesen (Zeile 7), dann die Adresse der ausgewählten Zelle angezeigt (Zeile 9) und Null in den ersten Steckplatz des zugewiesenen Speichers geschrieben. Als nächstes tritt das Programm in einen Zyklus ein, in dem es den im Speicher aufgezeichneten Wert an der Adresse in der Variablen "p" erhöht. Es zeigt auch die Prozesskennung von sich selbst an.
Die Prozess-ID ist für jeden laufenden Prozess eindeutig . Nachdem wir mehrere Exemplare gestartet haben, werden wir auf ein interessantes Ergebnis stoßen: Wenn Sie im ersten Fall nichts tun und nur mehrere Exemplare starten, sind die Adressen unterschiedlich. Dies fällt aber nicht unter unsere Theorie! Es ist wahr, da in modernen Distributionen die Funktion der Randomisierung des Speichers standardmäßig aktiviert ist. Wenn Sie es ausschalten, erhalten wir das erwartete Ergebnis - die Speicheradressen von zwei gleichzeitig ausgeführten Programmen stimmen überein.
Infolgedessen stellt sich heraus, dass zwei unabhängige Programme mit ihren eigenen privaten Adressräumen arbeiten, die wiederum vom Betriebssystem im physischen Speicher angezeigt werden . Daher wirkt sich die Verwendung von Speicheradressen innerhalb eines Programms in keiner Weise auf andere aus, und es scheint, dass jedes Programm über einen eigenen physischen Speicher verfügt, der ihm vollständig zur Verfügung steht. Die Realität ist jedoch, dass der physische Speicher eine gemeinsam genutzte Ressource ist, die vom Betriebssystem verwaltet wird.
Kohärenz
Ein weiteres wichtiges Thema innerhalb von Betriebssystemen ist die
Konsistenz . Dieser Begriff wird verwendet, wenn es um Probleme im System geht, die auftreten können, wenn mit vielen Dingen gleichzeitig im selben Programm gearbeitet wird. Konsistenzprobleme treten auch im Betriebssystem selbst auf. In früheren Beispielen mit Speicher- und Prozessorvirtualisierung haben wir festgestellt, dass das Betriebssystem viele Dinge gleichzeitig verwaltet - es startet den ersten Prozess, dann den zweiten und so weiter. Wie sich herausstellte, kann dieses Verhalten zu einigen Problemen führen. So haben beispielsweise moderne Multithread-Programme solche Schwierigkeiten.
Betrachten Sie das folgende Programm:

Das Programm in der Hauptfunktion erstellt mit dem Aufruf
Pthread_create () zwei Threads. In diesem Beispiel kann ein Thread als eine Funktion betrachtet werden, die neben anderen Funktionen im selben Speicherbereich ausgeführt wird, und die Anzahl der gleichzeitig gestarteten Funktionen ist eindeutig mehr als eins. In diesem Beispiel startet und führt jeder Thread die Funktion
worker () aus,
die wiederum einfach die Variable inkrementiert.Führen Sie dieses Programm mit dem Argument 1000 aus. Wie Sie vielleicht vermutet haben, sollte das Ergebnis 2000 sein, da jeder Thread die Variable 1000-mal erhöht hat. Es ist jedoch nicht alles so einfach. Versuchen wir, das Programm mit einer um eine Größenordnung höheren Anzahl von Wiederholungen auszuführen.

Wenn Sie eine Zahl eingeben, z. B. 100000, wird 200000 in der Ausgabe angezeigt. Wenn Sie die Zahl 100000 jedoch mehrmals ausführen, wird nicht nur nicht die richtige Antwort angezeigt, sondern es werden auch unterschiedliche falsche Antworten angezeigt. Die Antwort liegt in der Tatsache, dass zum Erhöhen der Anzahl drei Operationen erforderlich sind - Extrahieren der Nummer aus dem Speicher, Inkrementieren und anschließendes Zurückschreiben der Nummer. Da all diese Anweisungen nicht atomar implementiert sind (alle gleichzeitig), können solche seltsamen Dinge passieren. Dieses Problem wird als
Race Condition Programming -
Race Condition bezeichnet . Wenn unbekannte Kräfte zu einem unbekannten Zeitpunkt die Leistung Ihrer Operationen beeinträchtigen können.