Aufgabe 1: Ein-/Ausgabe
Bei der Betriebssystemprogrammierung geht es noch mehr als in anderen Disziplinen um Versuch und Irrtum. Die Hardware ist nicht zwingend immer gut und eindeutig dokumentiert, für manche Geräte ist es teilweise richtig schwer eine ordentliche Primärquelle zu finden. Nicht selten finden sich im Internet gar widersprüchliche Informationen. Aber selbst wenn wir über eine ausreichende Dokumentation wie bei dem Intel Manual verfügen, so sind die paar tausend Seiten auch keine leichte Lektüre, wir werden oft erschlagen von historischen Überbleibseln und unterschiedlichen Varianten.
Eine einfache Lösung lautet oft: Ausprobieren. Aber wie können wir unser Betriebssystem testen?
Die schnellste Variante ist eine Virtuelle Maschine, beliebt sind für unseren Einsatzzweck besonders Bochs und Qemu. Letzteres unterstützt mit KVM, der *Kernel-based Virtual Machine, auch CPU-Erweiterungen wie Intel VT und AMD-V, womit eine schnelle und realitätsnahe Virtualisierung der CPU ermöglicht wird. Das ist insbesondere für den Mehrkernbetrieb in MPStuBS relevant, denn nur KVM bietet "echte" Parallelität. Bei der Softwaremulation hingegen wird die Ausführung der Kerne serialisiert, wodurch viele Nebenläufigkeitsprobleme gar nicht auftreten.
Aber schlussendlich soll unser Betriebssystem auf echter Hardware laufen, und hierfür haben wir für euch einige Testrechner in den WinCIP gestellt. Dies sind Intel i5 der 1. Generation, haben zwei physikalische Kerne mit Hyperthreading, MPStuBS sieht somit vier Kerne. Sie haben alle 8 GB Ram, 250 GB Festplatte – was wir aber nicht verwenden wollen – und eine PS/2 Tastatur sowie Maus. Zudem sind sie über den COM1-Port – die serielle Schnittstelle – mit einem CIP Rechner verbunden.
Während früher das Betriebssystem erst auf Diskette kopiert, zum Testrechner getragen und dort dann gebootet werden musste – und nicht selten haben defekte Disketten dabei die Problemsuche unnötig verkompliziert – setzen wir hier inzwischen auf eine bequemere Variante: Die Kernel werden über das Preboot Execution Environment aus einem Netzwerkverzeichnis geladen, dazu seht ihr nach dem Boot ein Auswahlmenü, in welchem ihr euer Betriebssystem auswählen könnt.
Während der Coronasituation ist nun jedoch der Zutritt zum WinCIP nicht so leicht möglich. Aber auch dafür haben wir eine Lösung: Ihr könnt den Fernzugriff via VNC nutzen, um die Rechnern zu bedienen und den Bildschirminhalt der realen Hardware lokal zu sehen. Entweder ihr nutzt dazu einen entsprechenden VNC Client – ich kann hierfür Remmina empfehlen – oder ihr verwendet die Weboberfläche auf i4stubs.cs.fau.de, welche auch einen Webclient integriert hat.
Außerdem können über die Weboberfläche die Rechner neu gestartet werden. Die Buttons "On", "Off" und "Reset" senden dabei entsprechende Signale an den PC, während "Hard-Cycle" die Vorschlaghammermethode ist und für 25 Sekunden den Strom physikalisch trennt – bitte nur verwenden, wenn beispielsweise "Reset" auch nach einigen Dutzend Sekunden nicht funktioniert. Nun kann man damit natürlich hervorragend Kommilitonen ärgern, in den man ihnen beim Testen einfach den Strom trennt. Bitte tut das nicht! Wir setzen hier auf kollegiales Verhalten. Solltet ihr auf einen Testrechner, der auf der Weboberfläche mit einem Status "on" versehen ist, nicht per VNC zugreifen können, so wird dieser sehr wahrscheinlich von einem anderen Studierenden verwendet. Nehmt bzw. startet in diesem Fall einfach einen anderen Rechner.
Und versucht die Zeit zum Testen an der echten Hardware kurzzuhalten, besonders wenn ein erhöhter Andrang herrscht – nicht einfach im Hintergrund die VNC Verbindung offen halten! Sollte extrem hoher Andrang sein, und längere Zeit kein Rechner verfügbar sein, koordiniert die Benutzung bitte über IRC, wir haben hierfür den Kanal #i4stubs
eingerichtet. Ein Webclient ist auch verlinkt. Die Zugangsdaten bekommt ihr per Mail. Wir arbeiten derzeit noch am Ausbau, und haben dementsprechend auch weitere Testrechner verfügbar, jedoch mit etwas andere Hardware, wie zum Beispiel 8 Kerne. Sie sind primär für die Forschung gedacht. Wenn ihr aber auch auf diesen Rechner euer StuBS testen wollt, fragt bitte kurz im IRC nach, ob sie gerade belegt sind, sonst dürft ihr sie natürlich auch verwenden.
Falls ihr selbst zu Hause einen weiteren PC übrig habt, könnt ihr auch auf diesem euer Betriebssystem testen, in dem ihr es zum Beispiel auf einem USB Stick installiert. Für die Abgabe aber wollen wir sehen, dass euer Betriebssystem ordentlich auf einem unseren vier StuBS Testrechner läuft. Diese sind die ausschließliche Referenz.
Nun kennen wir die Testumgebung, aber was brauchen wir für die Entwicklungsumgebung? Theoretisch reichen Internet und ein PC mit SSH Zugang in den Informatik CIP, also unter Windows zum Beispiel mittels Putty. Oder ein halbwegs aktueller Webbrowser, damit könnt ihr euch über den HTML Client für Xpra auf der Webseite remote.cip.cs.fau.de ebenfalls an einen CIP Rechner anmelden. Für ein optimales Entwicklungserlebnis braucht ihr einen Rechner mit x64 Architektur und Unterstützung für die bereits erwähnte Hardwarevirtualisierung mittels KVM – was aber wohl auf fast jeden normalen Consumer-PC der letzten 10 Jahre zutrifft. Nur bei manche Laptops und Ultrabooks, welche auf der ARM Architektur basieren, wird es schwieriger: Sie können zwar in der Theorie auch verwendet werden, brauchen aber dafür einen Crosscompiler und können keine x64 Virtualisierung, sprich kein Qemu. In solchen Fällen lieber via SSH im CIP arbeiten.
Wir verwenden als Toolchain primär GNU Werkzeuge, entsprechend ist eine unixoide Umgebung sehr zu empfehlen. Ausgiebig getestet haben wir die Umgebung auf dem aktuellen Debian 10 – wie im CIP installiert – und Ubuntu Focal Fossa, aber auch alle anderen relevanten Distributionen werden sicherlich die von uns benötigten Werkzeuge über deren Paketverwaltung bequem anbieten. Unter Windows kann man die Entwicklung mit dem Windows Subsystem for Linux versuchen, und dort zum Beispiel die Ubuntu Distribution wählen. Derzeit bietet aber der von Microsoft kompilierte Linuxkernel kein KVM an, entsprechend kann nur Qemu zum Testen verwendet werden. Alternativ reicht auch ein in VirtualBox installiertes Debian, wir haben dazu ein vorgefertigtes Abbild, etwa 2 GB groß, welches bereits alle relevante Software installiert hat, auf der Webseite unter Entwicklungsumgebung veröffentlicht. Egal welche Variante ihr wählt, ihr müsst vermutlich in der Lage sein, selbst Software nachinstallieren zu können – Administratorberechtigungen sind ziemlich sicher notwendig.
Die wichtigste Software, die wir brauchen, ist natürlich ein C bzw. C++ Übersetzer. Ich verwende primär GCC, aber Clang funktioniert ebenso. Theoretisch sollte sowohl GCC als auch Clang ab Version 5 funktionieren, aber mit unserer kontinuierlichen Integration testen wir inzwischen nur noch beide Compiler ab Version 7.
Stichwort kontinuierliche Integration: Beide Übersetzer sind mit den weiteren benötigten Werkzeugen für die GitLab CI auch in Docker verfügbar, was natürlich bei Bedarf auch lokal von euch verwendet werden kann. Zu diesen zusätzlich benötigten Werkzeugen zählt der Netwide Assembler, welcher im Vergleich zum GNU Assembler für uns bessere Präprozessor Unterstützung bietet, ein Beispiel folgt in Aufgabe 2. Wer nun Angst bekommt: Wir leben im 21. Jahrhundert, für Assembler in StuBS gilt: So wenig wie möglich, so viel wie nötig. Und in einem Zusatzseminar erklären wir euch alle notwendigen Fertigkeiten. Daneben werden noch die build-essentials wie make
, strip
und objcopy
gebraucht, und zum Testen idealerweise Qemu mit KVM.
Unser Betriebssystem entkäfern wir mit dem GNU Debugger (GDB), auch hierzu geben wir in einem Zusatzseminar Tipps zur Verwendung. Mit der in Python verfassten statischen Code-Analyse cpplint kann die Konformität des Codingstyles geprüft werden. Um sein Betriebssystem auf eine CD oder USB-Stick zu bringen, werden noch die Dateien für den Bootloader GRUB gebraucht, sowie Xorriso, womit die ISO Abbilder erstellt werden können.
Nun wo wir alle Tools haben, können wir loslegen: StuBS kommt mit einem fertigen Makefile. Durch Eingabe von make qemu
wird der Kern gebaut und in Softwareemulation gestartet. Bei make kvm
wird die Hardwarebeschleunigung zugeschaltet. Durch das Anhängen von -gdb
wird der Kern zusammen mit einem in Qemu integrierten GDB Stub gestartet, und nach dem BIOS auf eine Eingabe von c
für continue gewartet, erst dann startet StuBS. Bitte beachten: GDB mit KVM funktioniert leider nicht ganz so wie wir es uns wünschen, besser zum Debuggen die Hardwareunterstützung nicht verwenden.
Mit dem Target netboot
wird euer Kern in das Netzwerkverzeichnis kopiert, ihr könnt ihn dann über die Testrechner booten. An all diese Targets könnt ihr auch noch Suffixe anfügen: Ein make qemu-gdb-dbg
wird den Kern zuerst mit für das debuggen geeignete Optimierungen kompilieren und diesen dann starten. Mit -noopt
deaktiviert man alle Optimierungen, wohingegen -opt
selbst aggressive Optimierungen und Link-Time-Optimization (LTO) aktiviert. Wenn man beispielsweise nur zu Debugzwecken gewisse Ausgaben haben will, kann man -verbose
nehmen, und im Kern das Makro DBG_VERBOSE
verwenden. Für die Abgabe sind weder opt
noch noopt
relevant – wir wollen sehen, dass der Kernel unter den Standardeinstellungen baut und funktioniert!
Um ein bootbares ISO Abbild zu bekommen, das man beispielsweise auf CD – das waren diese runden Frisbees mit Loch aus den 90ern – brennen kann, gibt es das make iso
Target. Wer nun keinen CD-Brenner mehr besitzt, kann dies stattdessen direkt in QEMU testen. Oder ihr bringt die ISO auf einen USB-Stick. Dazu müsst ihr zuerst das Gerät des USB-Sticks ZUVERLÄSSIG feststellen, beispielsweise sdb
, und dann wird dieser via sudo make usb-sdb
mit einem bootbaren StuBS bespielt. Der Zielrechner muss natürlich einen Legacy Boot von USB unterstützen. Und vertippt euch nicht – wenn ihr hier versehentlich eure Festplatte angebt, dann bootet euer Rechner nur noch StuBS. Entsprechend: Benutzung auf eigene Gefahr, wir übernehmen keinerlei Haftung.
Was ihr hingegen gefahrlos starten könnt, sind die Musterlösungen: mit make solution-2
wird unsere Beispiellösung von Aufgabe 2 ausgeführt. Da wir dieses Semester auch etwas Wert auf den Coding Style legen werden, gibt es mit lint
die Möglichkeit dies zu prüfen. Es wird dabei das Pythontool cpplint
aufgerufen, welches die Konformität zum Google C++ Coding Style – mit Anpassungen von uns – validiert. Es gibt noch weitere Targets, über help
kann man sich diese mit weiteren Informationen anzeigen lassen.
Sofern ihr noch nie mit Qemu gearbeitet habt, kann es passieren, dass ihr verzweifelt die Hotkeys sucht, um aus der Virtuellen Maschine wieder herauszukommen, da Tastatur und Maus von ihr gefangen wurden. Bei der aktuellen GTK Oberfläche müsst ihr dazu die linke Steuerung- und linke Alt-Taste gleichzeitig mit g
drücken – zum Beenden stattdessen q
. Falls euer Qemu noch die alte SDL basierende Oberfläche verwendet, werden die Eingabegeräte mit gleichzeitigem Drücken der rechte Steuerung- und rechte Alt-Tasten freigegeben. Zum Beenden muss dazu noch die 2
gedrückt werden, um in die Monitorkonsole zu gelangen, und danach den Befehl q
dort ausführen. Bei der Terminal basierten Curses Oberfläche, welche z. B. über SSH ausgeführt wird, muss man ebenfalls den Weg über die Monitorkonsole zum Beenden gehen. In diese Konsole kommt man mittels gleichzeitigem Drücken der linken Alt-Taste und 2
.
Für die Verbindung mit dem CIP empfiehlt sich eine passwortloser Login via SSH mittels privatem und öffentlichen Schlüssel. Dies ist nicht nur bequemer, sondern – richtig angewendet – in der Regel auch deutlich sicherer als Passwörter. Dazu im Terminal einfach mit dem Befehl ssh-keygen
ein neues Schlüsselpaar generieren. Für mich ist die vorgeschlagene Standarddatei in Ordnung, ein Passwort für den Schlüssel brauch ich an meinem privaten PC nicht. Anschließend kann ich den öffentlichen Schlüssel mit dem Befehl ssh-copy-id
in den CIP kopieren, er wird dadurch im dortigen Heimverzeichnis in der unter .ssh
liegenden authorized_keys Datei angefügt. Da die Heimverzeichnisse im Netz liegen, ist irgendein Informatik CIP Rechner als Ziel ausreichend, ich kann danach auf alle CIP Rechner passwortlos zugreifen.
Da ich noch meinen Benutzernamen mit angeben muss, kann ich lokal die ebenfalls im Heimverzeichnis unter .ssh
liegende config
anpassen. Für alle Zielrechner, welche auf .cip.cs.fau.de
enden, soll in meinem Fall der Benutzer uj66ojab
verwendet werden. Sofern ich bei ssh-keygen
den Pfad geändert hab, kann ich das mit der Option IdentityFile
angeben. Ich persönlich finde noch die Optionen zum Multiplexen der Verbindung praktisch, dadurch wird beim mehrfachen Einloggen die bestehende SSH Verbindung verwendet, was dann deutlich schneller geht. Je nachdem wie euer typischer Arbeitsablauf ist, kann dies ganz angenehm sein, ist aber nicht notwendig.
Die Details für die Konfigurationsoptionen findet ihr auf der Manualseite man ssh_config
– und natürlich in tausenden Artikeln auf Blogs oder StackOverflow. Auf der Webseite unter Entwicklungsumgebung ist auch das Skript setup-env.sh
verfügbar, welches neben dem Prüfen auf notwendigen Tools und Einstellungen euch auch die SSH Einrichtung abnehmen kann. Nach der Einrichtung sollte nun in StuBS sowohl das Ausführen einer Musterlösung als auch make netboot
funktionieren. Außerdem empfiehlt es sich, den öffentlichen Schlüssel in GitLab unter Einstellungen / SSH-Schlüssel einzutragen, damit ihr bequem – ohne Passworteingabe – von eurem Übungsrepo pullen und pushen könnt.