• 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

              Page Frame Allocator in StuBSmI

              Bernhard Heinloth

              2022-06-02

              Es gibt mehrere Möglichkeiten die unbenutzten Seiten im physikalischen Speicher zu verwalten – eine gute Übersicht findet sich z.B. im osdev-Wiki. Für die Aufgabe 3 soll ein Kompromiss aus kompakter aber einfacher Struktur genutzt werden: Linked-List

              Freispeicherlisten

              Es wird eine einfache verkettete Liste verwendet. Um das Allokieren einen Tick einfacher zu machen, verwenden wir hier statt einer Endadresse lieber eine Längenangabe, welche die Anzahl der vorhandenen freien Page Frames angibt

              struct PageList:
                  start (Zeiger auf anfang eines freien Bereiches, auf 4 KB ausgerichtet)
                  len (Anzahl der 4 KB Pages)
                  next (Zeiger auf nächsten PageList-Eintrag -- oder NULL)

              Wur können hier mit new schnell dynamisch ein neues Element erstellen und mit delete dann wieder freigeben (dürfen halt nur nicht zu viele Einträge werden, aber mit das sollte mit dem hier beschriebenen Vorgehen kein Problem sein).

              Grundlegenden Funktionen

              Das Allokieren ist einfach (𝒪(1)): Erstes Element der Liste nehmen, und von dem Bereich einfach den letzten Page Frame zurückgeben – hat den Vorteil, dass ich nur len anfassen muss (solange in dem Bereich mehrere Page Frames vorhanden sind).

              alloc():
                  Nimm erstes Element aus der Liste
                  Falls keine Einträge in der Liste: 
                      gib Null zurück
                  ansonst:
                      Ziel ist start + len * 0x1000
                      Reduziere len im Eintrag um 1
                      Falls len nun 0:
                          lösche den Eintrag
                      gib Ziel zurück
              }

              Beim zurückgeben einer nun nichtmehr benötigten Seite machen wir es uns sehr einfach: Es wird als Bereich mit nur einem Page Frame an den Anfang der Liste gehängt – damit wird es gleich beim nächsten alloc wieder verwendet, und wir brauchen keine Angst haben, dass unsere verkettete Liste zu groß wird!

              free(addr):
                  Füge einen neuen Eintrag an den Anfang der Liste mit { addr, 1 }

              Initialisierung

              Einfaches Vorgehen: Wir beginnen mit einer leeren Liste, fügen von der Multiboot MemoryMap den Speicher hinzu, der als frei gekennzeichnet ist, jeder Bereich ist ein Element. Danach gehen wir nochmal über diese MemoryMap, und entfernen aus eben hinzugefügten Bereichen den belegten Speicher wieder hinaus – Überlappungen sind ja möglich! Der Aufwand ist zwar 𝒪(n²), aber das ist OK. Außerdem entfernen wir noch weitere Bereiche die wir nicht als Page Frames ausgeben wollen.

              init():
                  1. über Multiboot::getMemoryMap() iterieren
                      Falls isAvailable():
                          addRange(getStartAddress(), getEndAddress())
                  2. nochmal über Multiboot::getMemoryMap() iterieren
                      Falls nicht isAvailable():
                          removeRange(getStartAddress(), getEndAddress())
                  3. weitere Speicherbereiche entfernen
                      removeRange(0, 0x00100000)  [< 1 MB für BIOS]
                      removeRange(0x00F00000, 0x00FFFFFF)  [ISA Memory Hole]
                      removeRange(&___KERNEL_START___, &___KERNEL_END___)
                      ...

              Hilfsfunktionen zum Löschen eines (beglegten Speicher-)Bereiches

              Idee: Wir gehen die Freispeicherliste durch und prüfen für jeden Eintrag (welcher einen freien Speicher repräsentiert) eine Überlappung mit dem via Parameter übergebenen belegten/zu entfernenden Speicherbereich. Dazu gibt es prinzipiell 4 Fälle

              • Vorbemerkung für die nachfolgenden Beispiele/Funktionen)
                • Start (from) ist inklusive
                • Ende (to) ist exklusive
                • es wird immer gleich mit ausgerichteten Adressen gearbeitet
              • Fall 1: zu entfernender Bereich Überdeckt den Listeneintrag vollständig
                Eintrag in Liste: 0x5000 - 0xa000            [_______________]
                Belegter Bereich: 0x3000 - 0xc000       [XXXXXXXXXXXXXXXXXXXXXXXXX]
                Resultat: kein freier Bereich
              • Fall 2: der zu entfernende Bereiche überschneidet sich mit dem Listeneintrag am Anfang
                Eintrag in Liste: 0x5000 - 0xa000            [_______________]
                Belegter Bereich: 0x3000 - 0x7000      [XXXXXXXXXXX]
                Resultat:         0x7000 - 0xa000                   [________]
              • Fall 3: der zu entfernende Bereiche überschneidet sich mit dem Listeneintrag am Ende
                Eintrag in Liste: 0x5000 - 0xa000            [_______________]
                Belegter Bereich: 0x8000 - 0xc000                      [XXXXXXXXXXX]
                Resultat:         0x5000 - 0x8000            [________]
              • Fall 4: zu entfernender Bereich ist echte Teilmenge des Listeneintrags
                Eintrag in Liste: 0x5000 - 0xa000            [_______________]
                Belegter Bereich: 0x6000 - 0x8000               [XXXXXXX]
                Resultat:         0x5000 - 0x6000            [_]         [___]
                            sowie 0x8000 - 0xa000

              Das nun als Pseudocode, dabei gibt der Eintrag in der Liste den freien Speicher von entry_start bis entry_end an, der zu entfernende Bereich von from bis to (auf Seitengrenzen gerundet, so dass der zu entfernende Bereich ggf. größer als durch die Parameter angegeben ist):

              removeRange(from, to):
                  from auf die Seitengrenze abrunden (from &= ~0xfff)
                  to auf die letzte Seitengrenze aufrunden (to =  (to + 0xfff) & (~0xfff))
                  Falls from < to:
                      Gehe durch die Einträge der Liste (beginnend bei head):
                          entry_start <- start des aktuellen Listenelements
                          entry_end <- entry_start + len * 0x1000
                          Falls from < entry_end und zugleich to > entry_start:
                              wir haben eine Überlappung & müssen nun die Fälle durchgehen
                              Falls from <= entry_start:
                                  Falls to >= entry_end: [Fall 1]
                                      die zu löschende Range überlappt vollständig den Eintrag
                                      -> Eintrag muss aus der Liste gelöscht werden
                                  andernfalls (to < entry_end): [Fall 2]
                                      start des aktuellen Listenelements auf to setzen
                                      Länge anpassen (entry_end - to) / 0x1000
                              andernfalls (from > entry_start):
                                  wir haben eine Überlappung beginnend in der Mitte [Fall 3 & 4]
                                  Länge des Eintrags anpassen (from - entry_start) / 0x1000
                                  Falls to < entry_end: [Fall 4]
                                      Neuen Eintrag { to, (entry_end - to) / 0x1000 } an die Liste anfügen

              Hilfsfunktionen zum Hinzufügen eines (freien Speicher-)Bereiches

              Diese Funktion ist relativ trivial, rundet lediglich auf die Seitengrenze (-> tatsächlicher freier Bereich ist kleiner oder gleich dem via Parameter übergebenen Bereich) und berechnet die Länge (= Anzahl der vollen Seiten in dem freien Bereich)

              addRange(from, to):
                  from auf die nächste Seite aufrunden (umgekehrt zu removeRange!)
                  to auf die letzte Seitengrenze abrunden (umgekehrt zu removeRange!)
                  Falls from < to:
                      removeRange(from, to) um ggf. doppelte/überlappende Einträge zu entfernen
                      len = (to - from) / 0x1000
                      füge { from, len } an das Ende der Liste an

              Zurück zur Übersicht

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

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