Du befindest dich hier: FSI Informatik » Prüfungsfragen und Altklausuren » Hauptstudiumsprüfungen » Lehrstuhl 4 » Betriebssysteme » Betriebssysteme (MPStuBS)

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

pruefungen:hauptstudium:ls4:bs:bs-2015-03-12 [03.04.2017 14:48] – angelegt Yannikpruefungen:hauptstudium:ls4:bs:bs-2015-03-12 [03.04.2017 14:49] (aktuell) Yannik
Zeile 1: Zeile 1:
-====== PRÜFUNGSPROTOKOLL  ======+====== Betriebssysteme (MPStuBS) ====== 
 +2015-03-12\\ 
 +Prüfer: Daniel Lohmann aka Daniel \\ 
 +Beisitzer: Daniel Danner
  
-Fach: Betriebssysteme (MPStuBS) \\ +Angenehme Atmosphaere, zu Beginn Unterhaltung mit Daniel, weil der Beisitzer noch nicht da war, ueber Sternzeichen und Geburtstage um die Weihnachtszeit rum.
-Prüfer: PD Daniel Lohmann \\ +
-Beisitzer: MSc. Christian Dietrich \\ +
-Datum: März 2016 \\+
  
 +==== Pruefungsverlauf ====
  
 +=== Einstieg ===
 + Was ist ein Betriebssystem?
 +    * Das innere meines Burgers *omnom*
 +    * Abstraktionsschicht zwischen Software und Hardware
 +    * Schutz
 +    * CPU-Multiplexing
  
-Es gab einen DIN-A3-Zettelden Daniel im Laufe der Prüfung voll gemalt hat. Manchmal musste ich auch was drauf schreiben.+=== Threads === 
 +Wie funktioniert das denn mit diesem Kontextwechsel. (Malt Kontrollfluss von f hin, Linie in Kernelebene, Lücke, magisch ploetzlich Kontrollfluss in g). Erzähl mal was da passiert. 
 +    * Scheduling-entscheidung (Sync, aber erst spaeter) 
 +    * Dispatchen durch active=dingens und toc_switch 
 +    * Was genau (asmcode) tut toc_switch? Wo ret-et das hin? 
 +    * Kann an active=dingens auch nach dem toc_switch erst machen? 
 +      * Was er hören wollte: neinweil wir sind nach dem toc_switch in nem anderen Kontext und active=anderesDingens wird passieren 
 +      * Wovon ich ihn überzeugen konnte: ja, wir müssen nur active=dasWasZuBeginnVonResumeActiveWarAlsoWirSelbst nehmenDas klappt dann (sofern man toc_settle noch anpasst)
  
-===== Vorbereitung =====+=== Synchronisation === 
 +Wir hatten da enter()/leave() ums resume() rumgewickelt. Wie wuerden wir denn das ohne Epilogebene machen? 
 +    * cli/sti ums Resume rumwickeln, oder lock-free-Liste oder anderweitig 
 +    * Irgendwie vermeiden, dass der aktive Thread in die readyqueue gehaengt wird, *bevor* seine Register gesichert wurden (sonst racecondition mit anderer CPU) 
 +    * Kann man alles machen, tut aber hart weh 
 +    * Besser: Spinlock nehmen. 
 +    * "Koennen wir da keinen Semaphor nehmen?" -- Nein, weil es ja kein Passives Warten in dem Kontext gibt. (Man koennte natuerlich eine "Was fuer Arbeit kann ich tun waehrend ich auf den Spinlock Warte"-Queue fuehren aber das ist doch alles frickel)
  
-Das ganze Zeugs, was auf den Folien steht, sollte man zwar mal gehört haben, aber man muss fast nichts auswendig können. Es geht mehr ums Verstehen. Auswendig können sollte man aber zum Beispiel den Stack, den toc-settle erzeugt. Überhaupt sind alle kniffligen Stellen im Übungsbetrieb wichtig, die sollte man drauf haben. 
  
-===== Einstieg =====+=== Ebenenmodell === 
 +Keine Fragen dazu, abgesehen von dem bisschen, das ich von mir aus erzählt hab
  
  
-Zum Einstieg wurde ich von Daniel gefragt, wozu man denn ein BS //braucht//. Man beachte, dass er nicht mehr seine Standardfrage gestellt hat, was denn ein BS //ist//. Ich wollte erst die Antworten aus den alten Protokollen abspulen - dann wurde ich aber unterbrochen und ich sollte beantworten wofür man es denn //braucht//. Also hab ich gesagt, dass man die CPU multiplexen muss, wenn man mehr Fäden als Prozessorkerne hat. Und dass ich den Speicher vor unerlaubtem Zugriff schützen muss. In dem Zusammenhang wollte er noch das Stichwort Supervisor-Modus haben. Dann sind wir noch drauf gekommen, dass ein BS ja die Maschine erst richtig hochfährt und dabei auch den Fäden jeweils einen Stack im Speicher zur Verfügung stellt. +==== Vorbereitung ==== 
- +Protokolle lesenFolien nochmal durchgehen, bei den Übungen aktiv mitgemachtÜbungen nochmal durchgesehen (insbesondere die schmutzigen Detailstoc_switch, und enter/leave)
-===== Unterbrechungen 1 ===== +
- +
- +
-Dann hat er aufs Papier einen Zeitstrahl gemalt und darauf lief dann ein Faden ab. Dann hieß es: „//Wenn der Faden jetzt die Unterbrechungen ausschaltet - kann er dann die CPU monopolisieren? Für immer? Er macht die Interrupts aus und danach kann er nicht mehr verdrängt werdenweil es ja keine Unterbrechungen mehr gibt. Oder?//“ Aus dem Zusammenhang war früher oder später klar, dass ich das widerlegen sollte. Obwohl das eine einfache Frage ist, waren meine Antworten eher so halbrichtig. Daniel hat dann gemeint, dass das Ausschalten der Interrupts ein Trap ins Betriebsystem sei, und dieses entscheide dann, ob der Faden überhaupt weiter machen darf, oder ob er verdrängt wird.  +
- +
-===== Scheduling ===== +
- +
- +
-Anschließend kam so die Frage, was es denn da überhaupt so für Arten gibt, beim Scheduling. +
-Da habe ich gesagt dass es eben kooperatives und präemptives Scheduling gibt. Beim kooperativen vertraut man darauf, dass die Fäden die CPU auch wieder freiwillig abgeben werden. Beim präemptiven werden die Fäden einfach „mit Gewalt“ von der CPU verdrängt.  +
- +
-Dann konnte ich mir aussuchen, welches der beiden Verfahren wir genauer besprechen. Oder vielleicht auch nur mit welchem wir anfangen.  Weil das Thema aber eh nicht meine Stärke war, habe ich gesagt, dass ich da keine Präferenz habe. ich konnte beide gleich gut und gleich schlecht. +
- +
-Anschließend hat Daniel alles mögliche auf dem Papier entwickelt. Wir hatten die Methode resume() - in dieser gab es aber fast keine Methodenaufrufe mehr, das meiste war „geinlined“ damit alles da drin statt findet. Dann hatten wir auch noch toc-go und toc-switch durchgesprochen. Dabei sollte ich sagen, welche Register denn da immer hin und her kopiert werden. Ich habe gesagt, dass es die nicht-flüchtigen sind. „Warum muss man die anderen, die flüchtigen, denn nicht sichern?“ wollte Daniel noch wissen. „Das macht doch der Compiler“ habe ich dann gesagt.  +
- +
-Irgendwann sollte ich dann auch noch den Stack hinmalen, den toc-settle erzeugt: +
- +
-Adresse vom zu startenden Faden \\ +
-0xcafebabe \\ +
-Adresse von kickoff \\ +
- +
-Dazu habe ich erklärt, dass als Rücksprungadresse die von kickoff gelesen wird und man dann dort hinspringt. Daniel hat dann eingehaktob das denn schon bei toc-settle passiere, dass ich dann in kickoff springe. Nein, habe ich gesagt, dass ist nicht so, denn toc-settle bereitet den stack ja nur vor. Eingetragen in das Stackpointerregister wird der dann erst in toc-go und dann beim ret von toc-go springe ich in kickoff. \\ +
-Über der Adresse von kickoff liegt dann im Stack eine Pseudo-Rücksprungadressedie nie angesprungen werden darf - aber wir brauchen sie, damit der Stack eben so aufgebaut ist, wie ein Stack eben immer aufgebaut ist, daher muss da halt ne Rücksprungadresse liegen. Darüber liegt dann das Argument von kickoff und das ist dann der zu startende Faden. +
-kickoff sollte ich dann auch noch hin malen. Habe ich dann wie in der Übung gemacht. Der Beisitzer meinte aber, Datentypen seien egal, und es müsste nicht so genau sein, es geht nur ums Prinzip: +
- +
-void kickoff(Thread* object){ \\ +
-object->action(); \\ +
-while(true){} \\ +
-+
- +
-===== Unterbrechungen 2 ===== +
- +
- +
- +
-Ich weiß nicht mehr wie es genau weiter ging. Irgendwann kam dann die Frage: „OKder Computer ist komplett ausgeschaltet. Jetzt schalte ich ihn ein und die Maschine fährt hoch. Sind die Interrupts in diesem Moment eigentlich ein oder aus?“ Also habe ich gesagtdass sie ausgeschaltet sind. Anschließend ging es darum, wo man sie denn einschaltet. Also hab ich gesagt, dass man alles vorbereitet, dann holt man sich den ersten Faden, dann macht man die Unterbrechungen an und lässt den Faden los laufen.  +
-Dann ging es darum, an welcher Stelle von all den Dingen, die wir jetzt auf dem Papier stehen hatten, man die genau einschaltet. Dabei haben wir keinen guard und kein enter/leave verwendet, sondern sti und cli. Da jetzt alles etwas anders aussah als ich es aus der Übung gewohnt war, kam ich dann durcheinander (der Code hatte im Prinzip die gleiche Funktion wie in der Übung, sah aber doch anders aus, weil wir meistens „geinlined“ haben anstelle von Funktionsaufrufen). Richtig war natürlich, dass man sie in kickoff einschaltet, unmittelbar vor object->action(). Denn hier springt man in die Anwendung rein, der Anwendungsprogrammierer soll sich aber damit nicht beschäftigen, also macht man es unmittelbar davor. Also so: +
- +
-void kickoff(Thread* object){ \\ +
-sti(); +
-object->action(); \\ +
-while(true){} \\ +
-+
- +
-Das ist der Falll, wenn ein Faden zum ersten Mal läuft. Wenn er schon mal gelaufen ist, kommt man aber nicht in kickoff raus, sondern in resume. Also muss man in resume, nach dem Aufruf von toc-switch auch noch mal sti() ausführen. Vorher ging es noch darum, wo man in resume cli() aufruft. Da gleich am Anfang von resume auf eine Warteschlange zugegriffen wurde und dieser Zugriff geschützt sein muss habe ich gleich am Anfang von resume() das cli() hin gemacht.  +
- +
-===== active-Zeiger ===== +
- +
- +
-Es ging dann auch noch um die Frage, wo ich denn den active-Zeiger aktualisiere. Der zeigt ja immer auf den Faden, der aktuell läuft. Macht man das vor oder nach toc-switch? Richtig ist, dass man es unmittelbar davor macht. Denn der Wert, den ich in den active-Zeiger schreiben will, liegt auf dem Stapel. Nach toc-switch habe ich aber einen ganz anderen Stapel.+
  
 +==== Besonderheiten ====
 +Ich kann bestätigen, dass Daniel unglaublich verunsichernd gucken kann, und auch nachfragt, obwohl alles richtig war. Ich habe dann immer einige Sekunden still überlegt und dann gesagt "doch, das stimmt so" und dann hats auch gepasst.
  
 +Generell war es eher kein Ausfragen, sondern eher ein Gespraech. Es gab nicht wenige Fragen, auf die es keine "richtige" Antwort gab, sondern bei denen es vielmehr um die Begruendung ging.
  
 +Lief gut, Sehr gute Note, Top Pruefer, gerne wieder.