Aber was passiert denn eigentlich wenn ich ein Programm in C oder C++ schreibe, dieses kompiliere und ausführe? Sind das denn nun Instruktionen für die Hardware (übersetzt in 0 und 1) oder sind das tatsächlich nur Befehle für das Betriebssystem?
Zuerstmal lädt das BS dein C/C++ Programm in den Speicher. Dabei kümmert es sich darum, dass für den Code und die Daten deines Programms überhaupt Arbeitsspeicher bereitsteht. Es weist Programm + Daten Stellen im Arbeitsspeicher zu und stellt dabei automatisch sicher, dass diese Stelle im Speicher nicht zufällig auch von einem anderen Programm benutzt wird. Allokiert dein Programm später mit malloc/new mehr Speicher, dann kümmert sich das Betriebssystem darum, dass auch dieser neue Speicherbereich zur Verfügung gestellt wird und nur von deinem Programm benutzt wird.
Weiterhin kümmert sich das BS um das Multitasking. BS + CPU arbeiten zusammen, um dein Programm immer wieder kurz zu unterbrechen und dann weiterlaufen zu lassen. Während dieser kurzen Unterbrechungen kümmert sich die CPU um ganz andere Programme, hat deren Werte in seinen Registern. Aber in dem Moment, wo der Scheduler des BS entschieden hat, dass dein Programm jetzt wieder an der Reihe ist, wird es fortgesetzt und merkt noch nichtmal was davon, dass es eben kurz unterbrochen war.
Wenn dein Programm nach der kurzen Unterbrechung wieder weiterläuft, kann es sein, dass in der Zwischenzeit der ihm zugewiesene Speicher vom RAM auf die Festplatte geschrieben werden musste, weil der RAM voll war und die anderen Programme ihn benötigten. Aber in dem Moment, wo dein Programm das nächste Mal z.B. auf eine Variable oder ein Array zugreifen will, merkt die CPU, dass dieser Speicherbereich gerade nicht im RAM ist, dein Programm wird wieder kurz unterbrochen (Interrupt), die CPU ruft die Speicherverwaltung vom BS auf und diese stellt den Speicherinhalt deines Programms im RAM wieder her (und verschiebt dafür vielleicht die Inhalte anderer Programme auf die Festplatte) und lässt dann dein Programm weiterlaufen. Dein Programm liest/schreibt in seinem Speicher und merkt gar nicht, dass es eben wieder kurz unterbrochen wurde oder dass der Speicherbereich eben kurz mal "weg" war.
Bis zu diesem Punkt meiner Beschreibung bestand dein Programm lediglich aus einfachen Sprunganweisungen, Schleifen, mathematischen Instruktionen und Lese/Schreiboperationen auf Speicherbereiche (Variablen) - Und trotzdem hat das BS hier schon enorm viel im Hintergrund beigetragen.
Jetzt will dein Programm zum ersten Mal ein Zeichen auf den Bildschirm schreiben. printf / cout. Dass da ein Fenster bereitgestellt wird, in das diese Ausgabe dargestellt wird, das macht das BS. Dass sich dieses Fenster verschieben und minimieren lässt, das macht das BS. Das BS stellt deinem Programm das Konsolenfenster bereit und der Befehl zur Textausgabe ruft im Hintergrund Funktionen des BS auf, die sich darum kümmern, dass der Text in der Konsole erscheint.
Als nächstes will dein Programm vielleicht eine Eingabe von der Tastatur lesen. Aber moderne BS erlauben User-Programmen keinen direkten Zugriff auf die Hardware mehr, weil sonst ein Programm leicht den ganzen PC zum Abstürzen bringen könnte und andere Programme beeinflussen könnte. Es ist alles abstrahiert und gekapselt. Dein Programm ruft scanf / cin auf und diese rufen über die Standardbibliothek die Funktionen des BS auf, um die aktuellen Tastatureingaben zu lesen. scanf gibt dir jetzt zurück, dass das Zeichen 'A' eingegeben wurde. Du weißt aber nicht, ob das Zeichen wirklich über die physische Tastatur eingegeben wurde oder vielleicht über die per Maus/Touch bedienbare Bildschirmtastatur oder ob es von einem anderen Programm erzeugt wurde. Um all diese Möglichkeiten kümmert sich das BS und schickt das 'A' über die Standardbibliothek an dein Programm.
Es geht weiter, dein Programm möchte seine Berechnungsergebnisse in einer Datei speichern. Du rufst in C/C++ die Befehle zum Öffnen der Datei mit Schreibzugriff auf, schreibst die Daten hinein und schließt die Datei wieder. Einfach, oder?
Hier beginnt das BS im Hintergrund jetzt richtig zu arbeiten. Denn Dateien/Dateipfade sind auch bloß nur ein abstraktes Konstrukt des BS und seinem Dateisystem, um die Milliarden an Bytes einer Festplatte irgendwie sinnvoll zu strukturieren.
Das BS prüft erstmal, wohin der Dateipfad überhaupt zeigt, den du da gerade öffnen willst. Auf der lokalen Festplatte? Oder vielleicht auf einem anderen Rechner im Netzwerk? Im letzteren Fall stellt es eine Verbindung zu diesem Rechner her, im ersteren Fall muss es "nur" auf die eigene Festplatte zugreifen. Nun prüft es, ob du als Nutzer und dein Programm, was du gerade ausführst, überhaupt die nötigen Berechtigungen habt, um an der gewünschten Stelle eine Datei zu erzeugen. Oder festzustellen, dass es dort schon eine Datei gibt und zu prüfen, ob du + dein Programm sie überschreiben dürft.
Während dein Programm die Datei zum Schreiben geöffnet hat, kümmert sich das BS automatisch darum, dass in der Zwischenzeit kein anderes Programm etwas in diese Datei schreibt. Und wenn dann dein Programm den Schreibvorgang beendet und die Datei schließt, räumt das BS auf -> eventuell automatisch gecachte Schreibbefehle tatsächlich physisch in die Datei = auf den Datenträger schreiben, Zeitstempel für "Letzte Bearbeitung" im Dateisystem für die Datei aktualisieren und zu guter letzt ggf. noch anderen Programmen Bescheid geben, dass die Datei gerade verändert wurde (z.B. einem Virenscanner).
Du merkst, dieser Text ist jetzt schon sehr lang, das BS hat schon enorm viel im Hintergrund geregelt aber dein kleines C/C++ Programm hat eigentlich noch gar nicht viel gemacht.
Threading, Netzwerk, Fenstermanager, Grafik, Benutzerverwaltung etc. waren noch gar nicht im Spiel.
Ja, streng genommen ist das BS auch nur ein Programm. Ein sehr spezielles Programm mit sehr speziellen Aufgaben, das sich darum kümmert, dass andere "normale" Programme sich um sehr vieles von der darunterliegenden Hardware nicht kümmern brauchen/dürfen, sondern einfach ablaufen können.
Ich denke, man MUSS das nicht zwingend alles wissen und verstehen, um Spiele zu programmieren. Zumindest nicht als Anfänger. Aber ich bin überzeugt, dass es auch nicht schadet. Ganz im Gegenteil: Wer solches Wissen lernt, lernt implizit auch sehr viel über Abstraktion und Softwarearchitektur. Wer sich immer mal wieder mit solchen Konzepten auseinandersetzt und sie verstehen lernt, lernt dabei ganz automatisch auch, wie man seine eigenen Programme gut in Komponenten und Schichten aufbauen kann. Oder wie man bestimmte Dinge effizient erledigt. Oder wie man manche Sachen sauber abstrahiert. Oder wie man Sicherheitskonzepte umsetzen sollte.