Du befindest dich hier: FSI Informatik » Prüfungsfragen und Altklausuren » Hauptstudiumsprüfungen » Lehrstuhl 4 » Prüfung vom 19.08.2024

Prüfung vom 19.08.2024

  • Prüfer: Volkmar
  • Beisitzer: Max
  • Note: 1.0

Gedächtnisprotokoll

P: Was wird denn in so Prüfungen immer gefragt?

I: Wosch hat immer mit Syscalls angefangen :)

P: Also gut, wieso verwenden wir Syscalls

I: Privilegientrennung (Safety, Security) - Ring 0 und 3, Prozesse wollen und sollen aber auch teilweise privilegiertes Zeug tun (write, IPC)

P: Wie funktionieren Syscalls in der Intel-Welt?

I: Entweder int 0x80 oder syscall/sysenter. User ruft Stub auf, Parameter werden entsprechend präpariert (dass der Kernel sie auch entgegennehmen kann), Software-Interrupt mit Kontextsicherung (sind jetzt im Ring 0), swapgs, Kernel nimmt Parameter entgegen und springt über Jumptable zur Implementierung des Syscalls

P: Und wie würde das bei der ZUSE ausschauen? Da haben wir ja keinen Ringwechsel, weil gibt ja nur einen, wieso macht man das nicht mit nem einfachen call?

I: *struggle* man will Userprogramme nicht patchen müssen, wenn man das Betriebssystem anpasst und sich die Einsprungaddressen ändern.

P: Was für Möglichkeiten haben wir, Parameter zu übergeben?

I: Register (wie bei uns), Komplexbefehl und in Instruktion kodiert (entweder mit Hardware, die swapgs und auf Stack legt, oder in Software im Kernel User-Code-Speicher auslesen), über User-Stack. Letzten beiden haben Varianten Problem bei total privaten Addressräumen. Muss Kernel sich über Fenster User-Pages mappen, potentiell langsam.

P: Gibts bei Register auch nen Nachteil?

I: Anzahl architekturabhängig begrenzt. Spätestens bei hypothetischen vararg Syscalls geht das nicht mehr.

P: Und was passiert, wenn wir wieder zurück zum User gehen? Muss da mit den Registern noch extra was passieren?

I: Ja, müssen wir nullen/wiederherstellen, um keine Kernel-Infos zu leaken. In unserm Fall nur die scratch-Register, non-scratch übernimmt die Syscall-Implementierung in der Hochsprache durch Einhalten der ABI.

P: Angenommen wir haben jetzt 7 solche Register (Linux, Intel x86), wieso können wir jetzt nicht 7 Parameter mitgeben?

I: Syscall-Nummer ist auch ein „Parameter“, also nur 6 restliche.

P: Und wie kann Linux jetzt doch mehr Daten rüberschieben?

I: *etwas Hilfe, dachte ich hätte das schon vorher teils beantwortet* Also entweder indem man Register aufteilt (spoiler: nö), oder man übergibt Pointer für User-Buffer.

P: Gibts da eventuell Probleme, wenn der Kernel auf den User-Buffer zugreifen will?

I: Erstmal Addressraum, muss teils wieder in Kernel extra gemappt werden. Ansonsten muss Addresse geprüft werden, ob kanonisch, ob überhaupt im logischen Addressraum des Users bzw lazily allozierbar (zB read in noch-nicht-present Stack-Page)

P: Ich sage das geht immer noch kaputt.

I: Ja, weil wir nicht nur den Startpointer überprüfen müssen, sondern den kompletten Buffer.

P: Ich sage das geht immer noch kaputt.

I: O.o help!?

P: Was passiert denn bei mehreren Threads?

I: Also bei uns kein Problem, Syscalls sind mit BKL im Epilog, da ist nur einer… Ohne, öhm…

P: Denk mal an ein umap.

I: Ah, gibt Probleme mit Race-Conditions wenn ein Thread unmappt während der andere Syscall noch drauf zugreift. Könnte dann in die Freispeicherliste eingehängt werden, neu vergeben werden während der Syscall noch fröhlich weiter doktort.

P: Wie löst man das?

I: Also entweder wie bei uns mit BKL…

P: Kindergarten!

I: Oder man synchronisiert das. zB würde ein unmap jedem anderen Syscall signalisieren, dass die entsprechende Page verschwindet, muss quittiert werden (andere Syscalls beenden sich dann zB mit nem Fehlercode an den User),danach erst darf die Page wieder als frei markiert werden.

P: Wie würde da ein optimistischer Ansatz aussehen?

I: öhm, idk?

P: Tipp: was passiert denn bei nem invaliden Zugriff?

I: Ah, GPF (nichtkanonisch) oder PF, im Handler schaut man sich den Kontext an und würde bei ner Violation den Syscall abbrechen lassen.

P: Kann man den Syscall so einfach zum User returnen lassen?

I: Erstmal Problem, weil iret die Instruktion nochmal ausführen lässt → nochmal PF. Entweder mit umbiegen vom Instruction-Pointer auf nen Error-Stub der dann returned, oder man mappt eine Dummy-Page und setzt ein entsprechendes Flag. Syscall muss dann nach jeder abgehandelten Page das Flag überprüfen und ggf mit Fehler beenden.


P: Okay, also muss man da schon recht viel denken, gehen wir mal weiter zu Segmentierung, da hatten wir ja mal Mischformen mit Paging behandelt, wie funktioniert das?

I: *gestikulierend erklärt* Addresse hat drei Bestandteile: Segmentnummer, Page-Teil und Offset. Erst Segmentierung, dann Page-Teil und Segmentaddresse addieren, damit pagen, anschließend Offset dranhängen. Gibts auch in der Version, dass man den Offset nicht beibehält, sondern den gesamten „unteren Teil“ mit der Segmentaddresse addiert. Vorteil ist, dass die Segmente nicht page-aligned sein müssen und man somit weniger Verschnitt hat.

P: Wie spielt da die Segmentlänge mit rein?

I: Man muss bei der Segmentierung überprüfen, ob man noch im gültigen Bereich ist. Verschwendet dann uU Platz wenn wir die Variante 1 verwenden, weil der Rest der teilgenutzten Page dann nicht verwendet werden kann.

P: Wofür habt ihr Segmente in StuBS verwendet?

I: Nur Code und Daten in der GDT.

P: Da waren noch mehr.

I: Also bei uns gibts nur die beiden.

P: Nur zwei?

I: Naja okay doch, sind schon mehr, jeweils für Ring 0 und 3 (hab zweites Ring 3 Code-Segment nicht erwähnt, wurde aber auch nicht angekreidet) und dann noch jeweils pro Core ein TSS-Segment.

P: Wozu gibts das TSS?

I: Früher angedacht für hardwaregestütztes Multithreading, mittlerweile (und bei uns) für Ringwechsel (Kickoff und bei Syscalls) und Core-Local-Storage.

P: Wie sieht das bei nem Ringwechsel konkret aus?

I: *brabbel* da gibts so Kontext mit Stackpointern und so, brauchen wir dann fürs swapgs für die Syscalls.

P: Warum machen wir uns den Aufwand?

<Zeit um> Antwort wäre: fürs Kickoff, Kontext für den initialen Ringwechsel vorbereiten (prepare context), sonst würde man ins Leere laufen…