GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Verwendung von Segmentierungsregistern

  1. Sie müssen einige wirklich alte Bücher gelesen haben, weil niemand für Real-Mode programmiert mehr;-) Im real-mode , erhalten Sie mit phyical address = segment register * 0x10 + offset die physikalische Adresse eines Speicherzugriffs , wobei der Offset ein Wert in einem der Mehrzweckregister ist. Da diese Register 16 Bit breit sind, ist ein Segment 64 KB lang und Sie können nichts an seiner Größe ändern, nur weil es kein Attribut gibt! Mit der * 0x10 Multiplikation wird 1 MB Speicher verfügbar, aber es gibt überlappende Kombinationen, je nachdem, was Sie in die Segmentregister eingeben und das Adressbuch . Ich habe keinen Code für den Real-Modus kompiliert , aber ich denke, es liegt am Betriebssystem, die Segmentregister einzurichten während des Ladens der Binärdatei, so wie ein Lader beim Laden einer ELF-Binärdatei einige Seiten zuweisen würde. Ich habe jedoch Bare-Metal-Kernel-Code kompiliert und musste diese Register selbst einrichten.

  2. Aufgrund von Architektureinschränkungen sind im flachen Modell vier Segmente obligatorisch. Im geschützten Modus die Segmentregister enthält nicht mehr die Basisadresse des Segments, sondern einen Segmentselektor was im Grunde ein Offset in die GDT ist. Abhängig vom Wert des Segmentselektors , befindet sich die CPU in einer bestimmten Berechtigungsstufe, dies ist die CPL (aktuelle Berechtigungsstufe). Die Segmentauswahl zeigt auf einen Segmentdeskriptor die eine DPL (Descriptor Privilege Level) hat, die schließlich die CPL des Segmentregisters ist wird mit diesem Selektor gefüllt (zumindest für den Codesegment-Selektor). Daher benötigen Sie mindestens ein Paar Segmentselektoren um den Kernel vom Userland zu unterscheiden. Darüber hinaus sind Segmente entweder Codesegmente oder Datensegmente, sodass Sie letztendlich vier Segmentdeskriptoren erhalten in der GDT.

  3. Ich habe kein Beispiel für ein ernsthaftes Betriebssystem, das die Segmentierung verwendet, nur weil die Segmentierung immer noch für die Rückwärtskompatibilität vorhanden ist. Die Verwendung des flachen Modellansatzes ist nichts anderes als ein Mittel, um es loszuwerden. Wie auch immer, Sie haben Recht, Paging ist viel effizienter und vielseitiger und auf fast allen Architekturen verfügbar (zumindest die Konzepte). Ich kann hier die Paging-Interna nicht erklären, aber alle Informationen, die Sie wissen müssen, finden Sie in dem hervorragenden Intel-Mann:Intel® 64 and IA-32 ArchitecturesSoftware Developer’s ManualVolume 3A:System Programming Guide, Part 1


Erweiterung von Benoits Antwort auf Frage 3...

Die Aufteilung von Programmen in logische Teile wie Code, konstante Daten, veränderbare Daten und Stack wird von verschiedenen Agenten zu unterschiedlichen Zeitpunkten vorgenommen.

Zunächst erstellt Ihr Compiler (und Linker) ausführbare Dateien, in denen diese Aufteilung angegeben ist. Wenn Sie sich eine Reihe ausführbarer Dateiformate (PE, ELF usw.) ansehen, werden Sie feststellen, dass sie eine Art von Abschnitten oder Segmenten oder wie auch immer Sie es nennen möchten, unterstützen. Neben Adressen und Größen und Speicherorten innerhalb der Datei tragen diese Abschnitte Attribute, die dem Betriebssystem den Zweck dieser Abschnitte mitteilen, z. dieser Abschnitt enthält Code (und hier ist der Einstiegspunkt), this - initialisierte konstante Daten, that - nicht initialisierte Daten (die normalerweise keinen Platz in der Datei einnehmen), hier etwas über den Stack, dort drüben die Liste der Abhängigkeiten (z. B. DLLs), usw.

Als nächstes, wenn das Betriebssystem mit der Ausführung des Programms beginnt, analysiert es die Datei, um zu sehen, wie viel Speicher das Programm benötigt, wo und welcher Speicherschutz für jeden Abschnitt benötigt wird. Letzteres erfolgt üblicherweise über Seitentabellen. Die Codepages sind als ausführbar und schreibgeschützt markiert, die konstanten Datenseiten sind als nicht ausführbar und schreibgeschützt markiert, andere Datenseiten (einschließlich der des Stacks) sind als nicht ausführbar und schreibgeschützt markiert. So sollte es normalerweise sein.

Häufig benötigen Programme schreibgeschützte und gleichzeitig ausführbare Bereiche für dynamisch generierten Code oder einfach um den bestehenden Code modifizieren zu können. Der kombinierte RWX-Zugriff kann entweder in der ausführbaren Datei angegeben oder zur Laufzeit angefordert werden.

Es kann andere spezielle Seiten wie Schutzseiten für die dynamische Stack-Erweiterung geben, sie werden neben den Stack-Seiten platziert. Beispielsweise beginnt Ihr Programm mit genügend Seiten, die für einen 64-KB-Stapel zugewiesen sind, und wenn das Programm dann versucht, über diesen Punkt hinaus zuzugreifen, fängt das Betriebssystem den Zugriff auf diese Schutzseiten ab, weist dem Stapel mehr Seiten zu (bis zur maximal unterstützten Größe) und verschiebt die Schutzseiten weiter. Diese Seiten müssen nicht in der ausführbaren Datei angegeben werden, das Betriebssystem kann sie selbst verarbeiten. Die Datei sollte nur die Stapelgröße(n) und vielleicht den Speicherort angeben.

Wenn das Betriebssystem keine Hardware oder keinen Code enthält, um den Codespeicher vom Datenspeicher zu unterscheiden oder Speicherzugriffsrechte durchzusetzen, ist die Aufteilung sehr formal. 16-Bit-Real-Mode-DOS-Programme (COM und EXE) hatten keine Code-, Daten- und Stapelsegmente, die auf besondere Weise markiert waren. COM-Programme hatten alles in einem gemeinsamen 64-KB-Segment und sie begannen mit IP=0x100 und SP=0xFFxx und die Reihenfolge von Code und Daten konnte beliebig sein, sie konnten praktisch frei miteinander verflochten werden. DOS-EXE-Dateien gaben nur die Startorte für CS:IP und SS:SP an, und darüber hinaus waren die Code-, Daten- und Stack-Segmente für DOS nicht zu unterscheiden. Alles, was es tun musste, war, die Datei zu laden, eine Verschiebung durchzuführen (nur für EXEs), das PSP (Program Segment Prefix, das den Befehlszeilenparameter und einige andere Steuerinformationen enthält) einzurichten, SS:SP und CS:IP zu laden. Es konnte den Speicher nicht schützen, da der Speicherschutz im Modus der realen Adresse nicht verfügbar ist, und daher waren die ausführbaren 16-Bit-DOS-Formate sehr einfach.


Linux
  1. So verwenden Sie BusyBox unter Linux

  2. Wie ich Cron unter Linux verwende

  3. Wann verwendet man Nohup?

  4. Linux – Verwendung von O_direct unter Linux?

  5. Wie man Man Pages unter Linux effektiv nutzt

Warum ich rxvt als Terminal verwende

Verwenden Sie den vi-Editor

So verwenden Sie Instagram im Terminal

Erfahren Sie, wie man Manpages effizient unter Linux verwendet

So verwenden Sie den PS-Befehl

So verwenden Sie den TOP-Befehl