• Navigation überspringen
  • Zur Navigation
  • Zum Seitenende
Organisationsmenü öffnen Organisationsmenü schließen
Friedrich-Alexander-Universität Lehrstuhl für Informatik 4 (Systemsoftware)
  • FAUZur zentralen FAU Website
  1. Friedrich-Alexander-Universität
  2. Technische Fakultät
  3. Department Informatik
Suche öffnen
  • English
  • Campo
  • StudOn
  • FAUdir
  • Stellenangebote
  • Lageplan
  • Hilfe im Notfall
  1. Friedrich-Alexander-Universität
  2. Technische Fakultät
  3. Department Informatik
Friedrich-Alexander-Universität Lehrstuhl für Informatik 4 (Systemsoftware)
Menu Menu schließen
  • Lehrstuhl
    • Team
    • Aktuelles
    • Kontakt und Anfahrt
    • Leitbild
    • 50-jähriges Jubiläum
    Portal Lehrstuhl
  • Forschung
    • Forschungsbereiche
      • Betriebssysteme
      • Confidential Computing
      • Eingebettete Systemsoftware
      • Verteilte Systeme
    • Projekte
      • AIMBOS
      • BALu
      • BFT2Chain
      • DOSS
      • Mirador
      • NEON
      • PAVE
      • ResPECT
      • Watwa
    • Projektkampagnen
      • maRE
    • Seminar
      • Systemsoftware
    Portal Forschung
  • Publikationen
  • Lehre
    • Sommersemester 2025
      • Applied Software Architecture
      • Ausgewählte Kapitel der Systemsoftware
      • Betriebssystemtechnik
      • Projekt angewandte Systemsoftwaretechnik
      • System-Level Programming
      • Systemnahe Programmierung in C
      • Systemprogrammierung 1
      • Verteilte Systeme
    • Wintersemester 2024/25
      • Betriebssysteme
      • Middleware – Cloud Computing
      • Systemprogrammierung 2
      • Verlässliche Echtzeitsysteme
      • Virtuelle Maschinen
      • Web-basierte Systeme
    Portal Lehre
  • Examensarbeiten
  1. Startseite
  2. Extern

Extern

Bereichsnavigation: Lehre
  • Betriebssystemtechnik
    • Vorlesung
      • Folien
      • Glossar
    • Übung
      • Aufgaben
      • Dokumentation
        • Blog
          • Entwicklungsumgebung
            • Assembler Crashkurs
              • C++ Crashkurs
                • 🔗 Testrechnerverwaltung
                • Kontakt
              • Evaluation

              Blog

              Aus der ELF in den Adressraum

              Bernhard Heinloth

              2022-06-23

              Für das Laden von ELF müssen bei uns in den allermeisten Fällen die Daten aus dem Bootmodul in den Zielspeicher kopiert werden: Durch die 512 Byte-Blöcke von TAR und den Eigenheiten vom ELF Daten Segment ist es im Gegensatz zu den Flat Binaries nur unter sehr besonderen Umständen möglich, Seiten direkt zu mappen – aus praktischen Gründen würde ich sogar ausschließlich auf das Kopieren setzen.

              Dieses Kopieren ist aber gar nicht so trivial, wie es sich im ersten Moment anhören könnte – denn wir müssen zwischen dem physikalischen Speicher, dem aktiven Mapping (= virtueller Speicher des Kernels) und dem virtuellen Speicher des gerade zu ladenden Prozesses unterscheiden!

              Zur Erinnerung: Beim Boot wird in der longmode.asm eine Identitätsabbildung der ersten 4 GB [mittels 2 MB Huge Pages] aufgesetzt (d.h. in diesem Bereich sind virtuelle und physikalische Adressen gleich). In vielen Gruppen wird dann auch bald auf ein eigenes Kernelmapping mit Identitätsabbildung lediglich der ersten 64 MB – des Kernelspaces – durch 4 KB Pages gewechselt, bevor dann irgendwann das Scheduling gestartet und dabei immer der virtuelle Adressraum des gerade laufenden Threads aktiviert wird.

              Bitte beachten: Der zweite Schritt, vor dem Starten der Threads bereits in einen eigenen virtuellen Adressraum mit fein-granularer 4 KB Abbildung zu wechseln, wurde in Aufgabe 3 nicht nur zum besseren Testen empfohlen (“After you’ve successfully activated your kernel mapping and verified the correct behavior of your applications, …”), sondern hat auch den Vorteil, dass wir das eigene Mapping bequem anpassen & ändern können – dies ist mit dem vorgegebenen initialen Mapping aus der longmode.asm nicht möglich!

              Wenn wir nun die ELF-LOAD-Segmente in den virtuellen Adressraum des Threads bringen wollen, müssen wir zuerst eine Seite allokieren. Unser PageFrameAllocator gibt uns bekanntlich einen Seitenrahmen / Kachel (= Seite im physikalischen Speicher) zurück, im konkreten Fall soll das jenseits der 64 MB liegen. Diese Kachel muss gemäß der virtualAddress im ELF Segment in den Zieladressraum eingeblendet werden (was trivial ist). Allerdings müssen noch die Inhalte aus der ELF-Datei im Bootmodul (Position offset) in diese Zielseite kopiert werden… Und hier dürfen wir nicht davon ausgehen, dass die Kachel bereits im aktiven Mapping eingeblendet ist: Selbst wenn wir noch das initiale Mapping verwenden, könnte die frisch allokierte Seite jenseits der identitätsabgebildeten 4 GB liegen…

              Wie löst man das Problem?

              Eine Möglichkeit wäre, dass man direkt vor dem Kopieren auf das Mapping des zukünftigen Threads wechselt. Dann kann man die Daten an die Zieladresse kopieren, gleich nachdem diese eingeblendet hat.

              Eine generischere (und etwas schönere/performantere) Lösung wäre, dass man die Seite temporär (für den Kopiervorgang) einfach im aktiven Kernelmapping einblendet: Wir blenden die Zielseite nicht nur im Adressraum des Threads, sondern auch noch an einer bestimmten Adresse im aktuellen virtuellen Adressraum ein, kopieren die Inhalte, und dann im Anschluss wird sie wieder ausgeblendet. Wir müssen nicht den ganzen TLB spülen (durch Ändern von cr3), sondern können mit invlpg gezielt den TLB Eintrag für diese bestimmte Adresse als ungültig markieren.

              Welche bestimmte Adresse nimmt man nun aber da?

              Wenn wir uns eine fixe Adresse ausdenken, so kann es sein, dass diese irgendwie anders verwendet wird… Aber der PageFrameAllocator kann uns ja eine Kachel im Kernelspace geben, und somit wird automatisch sicher gestellt, dass diese noch nicht verwendet wird. Und da wir im Kernelspace ja identitätsabbildung haben (phys = virt) können wir an diese Adresse nun die Zielseite mappen, Daten kopieren, und am Ende wird wieder die Identitätsabbildung hergestellt und die Kachel an den PageFrameAllocator zurück gegeben.

              Eine Optimierung wäre, diese Kachel von nun an zukünftig für weitere Kopien zu reservieren, dann spart man sich bei jeder Kopie unmap & free

              Beide Varianten werden sind für diese Aufgabe valid, auch wenn wir damit nicht absolut konform mit dem Multibootstandard sind: Wir gehen in beiden Fällen davon aus, dass die Multibootinformationen und die Bootmodule in den ersten 64 MB liegen – was zwar auf HW und Qemu/KVM der Fall ist, aber der Standard gibt uns diese Sicherheit eigentlich nicht:

              The Multiboot information structure and its related substructures may be placed anywhere in memory by the boot loader (with the exception of the memory reserved for the kernel and boot modules, of course)

              (da Multiboot selbst 32 bit ist, bedeutet das die ersten 4 GB).

              Aber um die Komplexität nun nicht zu erhöhen darf dieser Aspekt außer Acht gelassen werden.

              Zurück zur Übersicht

              Friedrich-Alexander-Universität
              Erlangen-Nürnberg

              Schlossplatz 4
              91054 Erlangen
              • Impressum
              • Datenschutz
              • Barrierefreiheit
              • Facebook
              • RSS Feed
              • Xing
              Nach oben