Sie befinden sich hier: Termine » Prüfungsfragen und Altklausuren » Hauptstudiumsprüfungen » Lehrstuhl 4 » Betriebssystem   (Übersicht)

Inhaltsverzeichnis

Betriebssystem

Prüfer: Daniel Lohmann
Beisitzer: Daniel Danner

Themengebiete: Betriebssysteme (MPStubs + Übung, 7.5 ECTS)

Datum: April 2013

Papier + Stift bereitgestellt; Daniel Lohmann hat einiges von dem was ich erklärt hat aufgemalt und dann ggf. vertiefende Fragen gestellt und erweitert.

Prüfer P, Student S.

Fragen

P: Was ist ein Betriebssystem?

S: Definition ist schwer, kommt auch auf die Anwendung an. Bibliothek, Monolithen, Exokernel genannt und grob erklärt.

P: Was zeichnet einen Monolithen aus?

S: Benutzer-/Systemmodus, Speicherschutz, mehrere Anwendungen, getrennte Adressräume. (Hat etwas gedauert bis ich genau auf den Unterschied kam, hatte da vorher nicht genau drüber nachgedacht.)

P: Was zeichnet einen Mikrokern aus?

S: Minimierung der Trusted Code Base, möglichst viel aus dem Kernel auslagern. Dispatcher muss in den Kernel wegen Adressraumwechsel, Scheduler aber nicht.

P: Kann ein Bibliothekssystem auch mehrere Anwendung unterstützen (also Scheduling)?

S: (War zuerst etwas verwirrt weil das in der Vorlesung nicht explizit genannt war.) Ja, kann man implementieren.

P: Was ist MPStubS?

S: (Mit Hilfe.) Bibliothekssystem, da kein Speicherschutz bzw. Benutzer-/Systemmodus, alles wird zusammen gelinkt.

P: Wie funktioniert toc_switch() zum Koroutinenwechsel?

S: Erklärt (siehe Übung/Vorlesung), nicht-flüchtige Register tauschen, dann ret auf dem neuen Stack.

P: Benötigt das spezielle Rechte?

S: Nein, geht auch im Benutzermodus.

P: Was ist das ideale Betriebssystem?

S: Das die spezifische Anwendung möglichst effizient ausführt. Eierlegende Wollmilchsau gibt es nicht.


P: Sie sind Betriebssystemsentwickler und sollten für folgende Anwendung ein Betriebssystem erstellen, was brauchen sie?

  main() {
      printf("Hallo, Welt!");
  }

S:

  • Bootloader
  • Ausgabetreiber für den Monitor
  • Startup-Code der main() aufruft und auch den Stack aufsetzt (den hab ich zuerst vergessen)
  • nach der main() im Startup-Code ein hlt, damit der Prozessor nicht weiter läuft

P: Der Kunde will noch ein getch(). Wie muss das System erweitert werden?

S:

  • Treiber für die Tastatur
  • Pollen des Register im Tastatur-Controller im Loop bis ein Zeichen gelesen wurde

P: Kunde merkt das der Lüfter immer an ist, wie kann man das beheben?

S:

  • aktives Warten ist schlecht, Interrupts verwenden
  • Interrupt-Handler speichert Zeichen in Buffer, getch() liest aus (kurz I/O-APIC, IDT, Interrupt-Routine erklärt)
  • sleep in getch()-Loop

P: Braucht man den Loop noch?

S:

Prinzipiell nein, da immer ein Zeichen geschrieben wurde. Aber wegen Spurious Interrupts ist es sinnvoll.

P: Wo ist das Problem im Loop?

S: Lost-Wakeup zwischen Überprüfung ob ein Zeichen gelesen wurde und sleep().

P: Wie behebt man das?

S: Interrupts vorher sperren; sti und sleep() müssen aber atomar sein (sti; hlt sind atomar auf x86).

P: Wo ist ein weiteres Problem?

S: Gemeinsamer Zustand (Buffer Index) in Interrupt-Handler und getch().

P: Wie behebt man das?

S:

  • hart synchronisieren: Interrupts vorher sperren, einseitige Synchronisation da der Interruptkontrollfluss nicht vom Anwendungskontrollfluss unterbrochen werden kann
  • weich synchronisieren: unterbrechungstransparenter Algorithmus

P: Wie könnte ein naiver Algorithmus aussehen?

S: interrupted flag im Handler setzen und im Loop in getch() prüfen, falls true Zeichen erneut auslesen (vgl. Time-Code in der Vorlesung).

P: Der Sohn des Auftraggebers hat dem Vater von Multiprozessorsystemen erzählt. Keyboard-Interrupts werden nur an die zweite CPU geschickt. Was müssen wir tun?

S:

  • Startup-Code muss main_ap() auf zweiter CPU starten
  • main_ap() einfach while(1) { hlt; }
  • IPI im Interrupt-Handler um Interrupt bei Keyboard-Interrupt an die erste CPU zu schicken und diese zu wecken

P: Gibt es bei der main_ap() ein Lost-Wakeup?

S: Nein. Denn Lost-Wakeup hat immer eine Test-Handle-Wettlaufsituation, in main_ap() wird nichts geprüft.

P: Was geht jetzt in getch() kaputt?

S: getch() kann jederzeit unterbrochen werden, einseitige Synchronisation reicht nicht mehr aus.

P: Wie löst man das?

S: Spinlock, lock()/unlock() um den kritischen Abschnitt.

P: Wo gibt es da ein Problem mit Interrupts?

S: Interrupts vor lock() sperren sonst gibt es Deadlock wenn getch() lock() macht und dann ein Interrupt kommt.

[Noch 2-3 Minuten Zeit.]

P: Wie implementiert man ein Spinlock?

S:

  lock() {
      while(TAS(&x, 1) == 1)
          ;
  }
  
  unlock() {
      x = 0;
  }

[Die folgenden Fragen gingen über den Stoff hinaus und waren stofflich nicht Teil der Prüfung.]

P: Weißt du wie man TAS auf der Hardware implementiert?

S: So grob. Über das Cache-Kohärenz Protokoll.

P: Wo ist das Problem damit? Wann wird eine Cache-Zeile ungültig?

S: Beim Schreiben bzw. wenn eine andere CPU den geänderten Wert lesen will? Also bei diesem TAS bei jedem Schleifendurchlauf.

P: Wie könnte man das mit CAS besser lösen? Hinweis, CAS vergleicht und tauscht dann.

S: CAS schreibt nur wenn der Lock nicht belegt ist, reduziert damit also das Cache-Trashing deutlich.

Fazit

Atmosphäre sehr angenehm, Fragen kamen nur von Daniel Lohmann. Note: sehr gut

Ich hab bei einigen Fragen etwas zu lange gezögert und kam nicht gleich auf die Antwort. Es lohnt sich, die „Programm“-Entwicklung schon zu Hause genau durchzugehen.