Ich weiß, dass die Ausgabe des Compilers, wenn der Quellcode in C ++ kompiliert wird, der Maschinencode (ausführbar) ist, von dem ich dachte, dass er Anweisungen direkt an die CPU enthält. Kürzlich las ich über Kernel und fand heraus, dass Programme nicht direkt auf die Hardware zugreifen können, sondern den Kernel durchlaufen müssen.
Wenn wir also einen einfachen Quellcode kompilieren, beispielsweise mit nur einer printf()
Funktion, und die Kompilierung den ausführbaren Maschinencode erzeugt, wird jeder Befehl in diesem Maschinencode direkt aus dem Speicher ausgeführt (sobald der Code vom Betriebssystem in den Speicher geladen wurde) oder wird ausgeführt muss jeder befehl im maschinencode noch über das betriebssystem (kernel) ausgeführt werden?
Ich habe eine ähnliche Frage gelesen . Es wurde nicht erklärt, ob der nach dem Kompilieren generierte Maschinencode eine Anweisung an die CPU ist oder ob der Kernel erneut durchlaufen werden muss, um die richtige Anweisung für die CPU zu erstellen. Was passiert also, nachdem der Maschinencode in den Speicher geladen wurde? Wird es durch den Kernel gehen oder direkt mit dem Prozessor sprechen?
quelle
printf
ist kein gutes Beispiel. Es wird in der C-Spezifikation explizit als eine Funktion definiert, die nur in "gehosteten" Implementierungen verfügbar ist (dh auf einem Kernel ausgeführt werden, im Gegensatz zu "freistehenden", für die möglicherweise keine erforderlich ist). Und auf den meisten Plattformenprintf
ist dies nur eine von Ihnen bereitgestellte Funktionlibc
, die eine Reihe von Aufgaben für Sie erledigt (einschließlich eines Systemaufrufs zum Drucken auf stdout). Es ist wirklich nicht anders als das Aufrufen vonlibvlc_media_list_add_media
oderPyObject_GetAttr
, mit der Ausnahme, dass einigeprintf
Implementierungen garantiert verknüpft werden können, ohne dass zusätzliche nicht standardmäßige-l
s hinzugefügt werden .Antworten:
Als jemand, der Programme geschrieben hat, die ohne Betriebssystem ausgeführt werden, biete ich eine endgültige Antwort.
Das hängt davon ab, wie das Programm geschrieben und erstellt wurde.
Sie könnten ein Programm schreiben (vorausgesetzt, Sie haben das Wissen), das überhaupt kein Betriebssystem erfordert.
Ein solches Programm wird als eigenständig bezeichnet .
Bootloader und Diagnoseprogramme sind typische Anwendungen für eigenständige Programme.
Das typische Programm, das in einer Host-Betriebssystemumgebung geschrieben und erstellt wird, wird standardmäßig in derselben Host-Betriebssystemumgebung ausgeführt.
Sehr explizite Entscheidungen und Aktionen sind erforderlich, um ein eigenständiges Programm zu schreiben und zu erstellen.
Richtig.
Dies ist eine Einschränkung, die durch einen CPU-Modus bedingt ist, den das Betriebssystem zum Ausführen von Programmen verwendet, und die durch bestimmte Build-Tools wie Compiler und Bibliotheken erleichtert wird.
Dies ist keine wesentliche Einschränkung für jedes Programm, das jemals geschrieben wurde.
Jede Anweisung wird von der CPU ausgeführt.
Eine Anweisung, die nicht unterstützt oder unzulässig ist (z. B. ein Prozess hat nicht genügend Berechtigungen), löst eine sofortige Ausnahme aus, und die CPU führt stattdessen eine Routine aus, um diesen ungewöhnlichen Zustand zu behandeln.
Eine printf () - Funktion sollte nicht als Beispiel für "einfachen Quellcode" verwendet werden .
Die Übersetzung von einer objektorientierten Programmiersprache auf hoher Ebene in Maschinencode ist möglicherweise nicht so trivial, wie Sie vermuten.
Anschließend wählen Sie eine der komplexesten Funktionen aus einer Laufzeitbibliothek aus, die Datenkonvertierungen und E / A durchführt.
Beachten Sie, dass Ihre Frage eine Umgebung mit einem Betriebssystem (und einer Laufzeitbibliothek) vorsieht.
Sobald das System hochgefahren ist und das Betriebssystem die Kontrolle über den Computer hat, werden Einschränkungen für die Funktionen eines Programms auferlegt (z. B. muss E / A vom Betriebssystem ausgeführt werden).
Wenn Sie ein eigenständiges Programm ausführen möchten (dh ohne Betriebssystem), müssen Sie den Computer nicht starten, um das Betriebssystem auszuführen.
Das hängt von der Umgebung ab.
Für ein eigenständiges Programm kann es ausgeführt werden, dh die Steuerung wird durch Springen zur Startadresse des Programms übergeben.
Für ein vom Betriebssystem geladenes Programm muss das Programm dynamisch mit gemeinsam genutzten Bibliotheken verknüpft werden, von denen es abhängig ist. Das Betriebssystem muss einen Ausführungsbereich für den Prozess erstellen, der das Programm ausführt.
Maschinencode wird ausgeführt durch die CPU.
Sie gehen nicht "durch den Kernel" , sondern "sprechen mit dem Prozessor" .
Der Maschinencode (bestehend aus Operationscode und Operanden) ist eine Anweisung an die CPU, die decodiert und die Operation ausgeführt wird.
Vielleicht sollten Sie sich als nächstes mit den CPU-Modi befassen .
quelle
gcc -O2 -ffreestanding my_kernel.c special_sauce.S
, um eine ausführbare Datei zu erstellen , bei der keine der normalen Bibliotheken oder Betriebssysteme vorhanden sind. (Natürlich benötigen Sie normalerweise ein Linker-Skript, um es in ein Dateiformat zu verlinken, das ein Bootloader laden möchte!)Der Kernel ist "nur" mehr Code. Es ist nur so, dass dieser Code eine Schicht ist, die sich zwischen den untersten Teilen Ihres Systems und der tatsächlichen Hardware befindet.
Alles läuft direkt auf der CPU, Sie wechseln einfach durch Ebenen, um etwas zu tun.
Ihr Programm "benötigt" den Kernel genauso wie die Standard-C-Bibliotheken, um den
printf
Befehl überhaupt verwenden zu können.Der eigentliche Code Ihres Programms läuft auf der CPU, aber die Verzweigungen, die der Code zum Ausdrucken auf dem Bildschirm erzeugt, durchlaufen den Code für die C-
printf
Funktion sowie verschiedene andere Systeme und Interpreter, von denen jedes seine eigene Verarbeitung vornimmt , um herauszufinden, wiehello world!
wird tatsächlich auf Ihrem Bildschirm gedruckt.Angenommen, Sie haben ein Terminalprogramm, das auf einem Desktop-Fenstermanager ausgeführt wird und auf Ihrem Kernel ausgeführt wird, der wiederum auf Ihrer Hardware ausgeführt wird.
Es gibt noch viel mehr, aber lassen Sie es uns einfach halten ...
hello world!
hello world!
auf die Konsole geschrieben hathello world!
mich geschrieben, können Sie es an Position setzenx
,y
bitte?“Dies ist eine massive Vereinfachung, die nur der Beschreibung dient. Hier seid Drachen.
Effektiv alles , was Sie tun , dass Hardware-Zugriff benötigt, sei es angezeigt, Speicherblöcke, die Bits von Dateien oder so etwas hat durch einige Gerätetreiber im Kernel genau arbeiten gehen , wie zu dem jeweiligen Gerät zu sprechen. Sei es ein Dateisystemtreiber über einem SATA-Festplatten-Controller-Treiber, der sich selbst auf einem PCIe-Bridge-Gerät befindet.
Der Kernel versteht es, all diese Geräte miteinander zu verbinden, und bietet eine relativ einfache Schnittstelle, über die Programme Dinge erledigen können, ohne wissen zu müssen, wie all diese Dinge selbst zu erledigen sind.
Desktop-Fenstermanager bieten eine Ebene, die bedeutet, dass Programme nicht wissen müssen, wie man Fenster zeichnet, und gut mit anderen Programmen zusammenarbeiten müssen, die versuchen, Dinge gleichzeitig anzuzeigen.
Schließlich bedeutet das Terminal-Programm, dass Ihr Programm nicht wissen muss, wie man ein Fenster zeichnet, wie man mit dem Kernel-Grafikkartentreiber spricht oder wie kompliziert es ist, mit Bildschirmpuffern und dem Timing der Anzeige umzugehen und tatsächlich zu wackeln Datenleitungen zum Display.
Es wird alles von Schichten auf Schichten von Code gehandhabt.
quelle
Das hängt von der Umgebung ab. Bei vielen älteren (und einfacheren!) Computern wie dem IBM 1401 lautet die Antwort "Nein". Ihr Compiler und Linker haben eine eigenständige "Binärdatei" ausgegeben, die überhaupt ohne Betriebssystem ausgeführt wurde. Als Ihr Programm aufhörte zu laufen, haben Sie ein anderes geladen, das auch ohne Betriebssystem lief.
In modernen Umgebungen ist ein Betriebssystem erforderlich, da nicht immer nur ein Programm gleichzeitig ausgeführt wird. Die gleichzeitige Verteilung von CPU-Kern (en), RAM, Massenspeichergerät, Tastatur, Maus und Bildschirm auf mehrere Programme erfordert eine Koordinierung. Das Betriebssystem bietet das. In einer modernen Umgebung kann Ihr Programm nicht nur die Festplatte oder SSD lesen und schreiben, sondern muss das Betriebssystem bitten, dies in seinem Namen zu tun. Das Betriebssystem empfängt solche Anforderungen von allen Programmen, die auf das Speichergerät zugreifen möchten, implementiert beispielsweise Zugriffssteuerungen (normale Benutzer können nicht in die Dateien des Betriebssystems schreiben), stellt sie in die Warteschlange und sortiert die zurückgegebenen Informationen zu den richtigen Programmen (Prozessen).
Darüber hinaus unterstützen moderne Computer (im Gegensatz zum 1401) den Anschluss einer Vielzahl von E / A-Geräten, nicht nur die, die IBM früher verkaufte. Ihr Compiler und Linker kann möglicherweise nicht alle Möglichkeiten kennen. Beispielsweise kann Ihre Tastatur über PS / 2 oder USB angeschlossen sein. Mit dem Betriebssystem können Sie gerätespezifische "Gerätetreiber" installieren, die mit diesen Geräten kommunizieren können, dem Betriebssystem jedoch eine gemeinsame Schnittstelle für die Geräteklasse bieten. Ihr Programm und sogar das Betriebssystem müssen also nichts anderes tun, um Tastatureingaben von einem USB-Gerät gegenüber einer PS / 2-Tastatur abzurufen oder beispielsweise auf eine lokale SATA-Festplatte gegenüber einem USB-Speichergerät zuzugreifen auf einem NAS oder SAN. Diese Details werden von Gerätetreibern für die verschiedenen Gerätecontroller verarbeitet.
Für Massenspeichergeräte bietet das Betriebssystem auf allen einen Dateisystemtreiber, der für Verzeichnisse und Dateien dieselbe Schnittstelle bietet, unabhängig davon, wo und wie der Speicher implementiert ist. Auch hier macht sich das Betriebssystem Sorgen um die Zugriffskontrolle und die Serialisierung. Im Allgemeinen sollte zum Beispiel dieselbe Datei nicht von mehr als einem Programm gleichzeitig zum Schreiben geöffnet werden, ohne durch einige Rahmen zu springen (gleichzeitige Lesevorgänge sind jedoch im Allgemeinen in Ordnung).
Ja, in einer modernen Universalumgebung brauchen Sie wirklich ein Betriebssystem. Aber auch heute gibt es Computer wie Echtzeit-Controller, die nicht kompliziert genug sind, um einen zu benötigen.
In der Arduino-Umgebung gibt es zum Beispiel kein wirkliches Betriebssystem. Klar, es gibt eine Menge Bibliothekscode, den die Build-Umgebung in jede "Binärdatei" einbindet, die sie erstellt. Da dieser Code jedoch von Programm zu Programm nicht permanent vorhanden ist, handelt es sich nicht um ein Betriebssystem.
quelle
Ich denke, viele Antworten missverstehen die Frage, die darauf hinausläuft:
Grundsätzlich führt die CPU den Maschinencode direkt aus . Es wäre wesentlich langsamer, wenn der Kernel alle Anwendungen ausführen würde. Es gibt jedoch einige Einschränkungen.
Wenn ein Betriebssystem vorhanden ist, ist es Anwendungsprogrammen normalerweise untersagt, bestimmte Anweisungen auszuführen oder auf bestimmte Ressourcen zuzugreifen. Wenn beispielsweise eine Anwendung einen Befehl ausführt, der die Systeminterrupt-Tabelle ändert, springt die CPU stattdessen zu einem OS-Ausnahmebehandler, sodass die fehlerhafte Anwendung beendet wird. Außerdem dürfen Anwendungen normalerweise nicht in den Gerätespeicher lesen / schreiben. Der Zugriff auf diese speziellen Speicherbereiche erfolgt über die Kommunikation des Betriebssystems mit Geräten wie Grafikkarte, Netzwerkschnittstelle, Systemuhr usw.
Die Einschränkungen, die ein Betriebssystem Anwendungen auferlegt, werden durch spezielle Funktionen der CPU wie Privilegierungsmodi, Speicherschutz und Interrupts erreicht. Obwohl jede CPU, die Sie in einem Smartphone oder PC finden würden, über diese Funktionen verfügt, ist dies bei bestimmten CPUs nicht der Fall. Diese CPUs benötigen in der Tat spezielle Kernel, die den Anwendungscode "interpretieren", um die gewünschten Funktionen zu erreichen. Ein sehr interessantes Beispiel ist der Gigatron , ein Computer mit 8 Befehlen, der aus Chips aufgebaut werden kann und einen Computer mit 34 Befehlen emuliert.
Einige Sprachen wie Java "kompilieren" zu etwas, das als Bytecode bezeichnet wird und eigentlich kein Maschinencode ist. Obwohl sie in der Vergangenheit zum Ausführen der Programme interpretiert wurden, wird heutzutage in der Regel die sogenannte Just-in-Time-Kompilierung verwendet, sodass sie als Maschinencode direkt auf der CPU ausgeführt werden.
Ausführen von Software auf einer virtuellen Maschine, bei der der Maschinencode von einem Programm namens Hypervisor "interpretiert" werden musste . Aufgrund der enormen Nachfrage der Industrie nach VMs haben die CPU-Hersteller Funktionen wie VTx zu ihren CPUs hinzugefügt, damit die meisten Anweisungen eines Gastsystems direkt von der CPU ausgeführt werden können. Wenn Sie jedoch Software ausführen, die für eine inkompatible CPU in einer virtuellen Maschine entwickelt wurde (z. B. die Emulation eines NES), muss der Maschinencode interpretiert werden.
quelle
Wenn Sie Ihren Code kompilieren, erstellen Sie so genannten "Objekt" -Code, der (in den meisten Fällen) (
printf
beispielsweise ) von Systembibliotheken abhängt. Anschließend wird Ihr Code von einem Linker umschlossen, der eine Art Programmladeprogramm hinzufügt, das Ihr bestimmtes Betriebssystem unterstützt Erkennen Sie, warum Sie ein für Windows kompiliertes Programm nicht unter Linux ausführen können, und wissen Sie, wie Sie Ihren Code entpacken und ausführen können. So ist Ihr Programm wie ein Fleisch in einem Sandwich und kann nur als ganzes Bündel gegessen werden.Nun, es ist halbwegs wahr. Wenn es sich bei Ihrem Programm um einen Kernelmodustreiber handelt, können Sie direkt auf Hardware zugreifen, wenn Sie wissen, wie man mit Hardware "spricht". In der Regel (insbesondere bei nicht dokumentierter oder komplizierter Hardware) verwenden die Benutzer jedoch Treiber, die Kernelbibliotheken sind. Auf diese Weise können Sie API-Funktionen finden, die wissen, wie man auf fast menschenlesbare Weise mit Hardware kommuniziert, ohne dass Adressen, Register, Timing und viele andere Dinge bekannt sein müssen.
Nun, der Kernel ist wie eine Kellnerin, deren Aufgabe es ist, Sie zu einem Tisch zu führen und Ihnen zu dienen. Das einzige, was es nicht kann - es ist Essen für dich, das solltest du selbst tun. Ebenso wie Ihr Code entpackt der Kernel Ihr Programm in einen Speicher und startet Ihren Code, der Maschinencode, der direkt von der CPU ausgeführt wird. Ein Kernel muss Sie nur beaufsichtigen - was Sie dürfen und was Sie nicht dürfen.
Maschinencode, der nach dem Übersetzen generiert wird, ist eine Anweisung an die CPU direkt. Daran besteht kein Zweifel. Das Einzige, was Sie beachten müssen, ist, dass nicht der gesamte Code in der kompilierten Datei der tatsächliche Maschinen- / CPU-Code ist. Linker hat Ihr Programm mit einigen Metadaten umhüllt, die nur der Kernel interpretieren kann, als Hinweis darauf, was mit Ihrem Programm geschehen soll.
Handelt es sich bei Ihrem Code nur um einfache Opcodes wie das Hinzufügen von zwei Registern, wird er direkt von der CPU ohne Unterstützung des Kernels ausgeführt. Wenn Ihr Code jedoch Funktionen aus Bibliotheken verwendet, werden solche Aufrufe vom Kernel unterstützt, wie zum Beispiel von der Kellnerin, wenn Sie dies wünschen in einem Restaurant zu essen, würde man einem Werkzeug geben - Gabel, Löffel (und immer noch ihr Vermögen), aber was man damit machen wird - es hängt von seinem "Code" ab.
Nun, nur um Flammen in Kommentaren zu vermeiden - es ist ein wirklich stark vereinfachtes Modell, von dem ich hoffe, dass es OP hilft, grundlegende Dinge zu verstehen, aber gute Vorschläge zur Verbesserung dieser Antwort sind willkommen.
quelle
Grundsätzlich gehen nur Systemaufrufe an den Kernel. Alles, was mit E / A oder Speicherzuweisung / Freigabe zu tun hat, führt normalerweise zu einem Systemaufruf. Einige Anweisungen können nur im Kernel-Modus ausgeführt werden und führen dazu, dass die CPU eine Ausnahme auslöst. Ausnahmen führen zu einem Wechsel in den Kernel-Modus und einem Sprung in den Kernel-Code.
Der Kernel verarbeitet nicht jede Anweisung in einem Programm. Das System ruft einfach auf und wechselt zwischen den laufenden Programmen, um die CPU gemeinsam zu nutzen.
Eine Speicherzuweisung im Benutzermodus (ohne Kernel) ist nicht möglich. Wenn Sie auf Speicher zugreifen, auf den Sie nicht zugreifen dürfen, bemerkt die zuvor vom Kernel programmierte MMU eine Ausnahme auf CPU-Ebene (Segmentierungsfehler) , was den Kernel auslöst und der Kernel das Programm beendet.
Das Ausführen von E / A im Benutzermodus (ohne den Kernel) ist nicht möglich. Wenn Sie auf E / A-Ports oder -Register für Geräte oder Adressen zugreifen, die mit Geräten verbunden sind (eines oder beide werden für die Ausführung von E / A benötigt), lösen diese ein aus Ausnahme in gleicher Weise.
Hängt vom Typ der ausführbaren Datei ab.
Kernel vermitteln nicht nur den gemeinsamen Zugriff auf RAM und Hardware, sondern führen auch eine Loader-Funktion aus.
Viele "ausführbare Formate", wie ELF oder PE, enthalten zusätzlich zum Code Metadaten in der ausführbaren Datei, die vom Loader verarbeitet werden. Lesen Sie die blutigen Details über Microsofts PE - Format für weitere Informationen.
Diese ausführbaren Dateien verweisen auch auf Bibliotheken (Windows-
.dll
oder Linux-Shared-Object-.so
Dateien) - ihr Code muss enthalten sein.Wenn Ihr Compiler eine Datei erstellt, die von einem Betriebssystem-Loader verarbeitet werden soll, und dieser Loader nicht vorhanden ist, funktioniert er nicht.
Sicher. Sie müssen das Betriebssystem davon überzeugen, Ihren Rohcode auszuführen, ohne Metadaten zu verarbeiten. Wenn Ihr Code Kernel-APIs aufruft, funktioniert er immer noch nicht.
Wenn Sie diese ausführbare Datei auf irgendeine Weise von einem Betriebssystem laden (dh wenn Rohcode geladen und ausgeführt werden kann), befindet sie sich weiterhin im Benutzermodus. Wenn Ihr Code auf Dinge zugreift, die im Benutzermodus verboten sind, im Gegensatz zum Kernelmodus, wie nicht zugeteilter Speicher oder E / A-Geräteadressen / -register, stürzt er mit Berechtigungen oder Segmentverletzungen ab (Ausnahmen gehen wiederum in den Kernelmodus und werden behandelt) dort) und wird immer noch nicht funktionieren.
Dann wird es funktionieren.
quelle
TL; DR-Nr.
Die Arduino-Entwicklung ist eine aktuelle Umgebung, in der es kein Betriebssystem gibt. Vertrauen Sie mir, bei einem dieser Babys haben Sie keinen Platz für ein Betriebssystem.
Ebenso hatten Spiele für das Sega Genesis kein Betriebssystem, auf das Sega zurückgreifen konnte. Sie haben gerade Ihr Spiel in 68K Assembler erstellt und direkt auf das Bare Metal geschrieben.
Oder wo ich mir die Zähne geschnitten habe, um Embedded-Arbeit am Intel 8051 zu leisten. Wenn Sie wieder nur ein 2716-Eprom mit einer Grundfläche von 2k * 8 haben, haben Sie keinen Platz für ein Betriebssystem.
Dies setzt natürlich eine sehr breite Verwendung des Wortes application voraus. Als rhetorische Frage lohnt es sich, sich zu fragen, ob eine Arduino-Skizze tatsächlich eine Anwendung ist.
quelle
Ich möchte nicht andeuten, dass die anderen Antworten nicht für sich genommen stimmen, aber sie enthalten viel zu viele Details, die für Sie leider immer noch sehr undurchsichtig sind.
Die grundlegende Antwort ist, dass der Code direkt auf dem Prozessor ausgeführt wird. Und nein, der Maschinencode "spricht" niemanden an, es ist umgekehrt. Der Prozessor ist die aktive Komponente und alles, was Sie in Ihrem Computer tun, wird von diesem Prozessor erledigt (ich vereinfache die Dinge hier ein wenig, aber das ist im Moment in Ordnung). Der Prozessor liest den Code, führt ihn aus und spuckt die Ergebnisse aus. Der Maschinencode ist nur Nahrung für den Prozessor.
Ihre Verwirrung rührt von der Verwendung des Wortes Hardware her. Obwohl die Aufteilung nicht mehr so eindeutig ist wie früher, ist es besser, wenn Sie in Bezug auf Peripheriegeräte denken, als einfach alles Hardware aufzurufen. Befindet sich auf Ihrem Computer ein Betriebssystem oder ähnliches, muss Ihr Programm seine Dienste für den Zugriff auf die Peripheriegeräte verwenden, aber der Prozessor selbst ist kein Peripheriegerät, sondern die Hauptverarbeitungseinheit, auf der Ihr Programm direkt ausgeführt wird.
Kernel, Betriebssysteme und ähnliche dazwischen liegende Schichten werden normalerweise nur in größeren Systemen verwendet, in denen erwartet wird, dass mehrere Programme ausgeführt werden und das System verwalten muss, wie diese Programme die Peripheriegeräte des Computers verwenden können (recht häufig auf dem Computer) gleiche Zeit). In diesen Fällen können laufende Programme nur mit dem System auf diese Peripheriegeräte zugreifen, das über die Freigabe entscheidet und sicherstellt, dass keine Konflikte vorliegen. Kleine Systeme, bei denen keine Verwaltung zwischen konkurrierenden Programmen erforderlich ist, weil es keine gibt, haben häufig überhaupt kein zugrunde liegendes System, und das einzelne Programm, das normalerweise auf diesen Systemen ausgeführt wird, kann mehr oder weniger frei mit den Peripheriegeräten tun, was es will.
quelle
Das BIOS, das beim Einschalten auf Ihrem Computer ausgeführt wird, ist ausführbarer Code, der im ROM gespeichert ist. Es besteht aus Maschinenanweisungen und Daten. Es gibt einen Compiler (oder Assembler), der dieses BIOS aus dem Quellcode zusammenstellt. Dies ist ein Sonderfall.
Weitere Sonderfälle sind das Bootstrap-Programm, mit dem der Kernel und der Kernel selbst geladen werden. Diese Sonderfälle werden in der Regel in einer anderen Sprache als C ++ codiert.
Im Allgemeinen ist es viel praktischer, wenn der Compiler einige Anweisungen erstellt, die Systemdienste aufrufen, die von einem Kernel oder von Bibliotheksroutinen bereitgestellt werden. Es macht den Compiler viel leichter. Dadurch wird der kompilierte Code auch leichter.
Am anderen Ende des Spektrums befindet sich Java. In Java übersetzt der Compiler den Quellcode nicht in Maschinenanweisungen, da dieser Begriff normalerweise verstanden wird. Stattdessen wird der Quellcode in "Maschinenanweisungen" für eine imaginäre Maschine übersetzt, die als Java Virtual Machine bezeichnet wird. Bevor ein Java-Programm ausgeführt werden kann, muss es mit der Java-Laufzeitumgebung kombiniert werden, die einen Interpreter für die Java Virtual Machine enthält.
quelle
In der guten alten Zeit war Ihr Programm dafür verantwortlich, alles zu tun, was während der Ausführung Ihres Programms getan werden musste, entweder indem Sie es selbst tun oder indem Sie Bibliothekscode hinzufügen, den andere in Ihr Programm geschrieben haben. Das Einzige, was im Computer daneben lief, war der Code, den Sie in Ihrem kompilierten Programm lesen konnten - wenn Sie Glück hatten. Auf einigen Computern musste Code über Schalter eingegeben werden, bevor mehr ausgeführt werden konnte (der ursprüngliche "Bootstrap" -Prozess), oder sogar Ihr gesamtes Programm wurde auf diese Weise eingegeben.
Es stellte sich schnell heraus, dass es nett war, Code zum Laden und Ausführen von Programmen laufen zu lassen. Später stellte sich heraus, dass Computer leistungsfähig genug waren, um das gleichzeitige Ausführen mehrerer Programme zu unterstützen, indem die CPU zwischen ihnen umgeschaltet wurde, insbesondere wenn die Hardware helfen konnte, aber die zusätzliche Komplexität der Programme sich nicht gegenseitig auf die Füße stellte (zum Beispiel Wie gehe ich mit mehreren Programmen um, die versuchen, Daten gleichzeitig an den Drucker zu senden?
All dies führte dazu, dass eine große Menge von Hilfecode aus den einzelnen Programmen in das "Betriebssystem" verschoben wurde, mit einer standardisierten Methode, den Hilfecode aus Benutzerprogrammen aufzurufen.
Und dort sind wir heute. Ihre Programme laufen auf Hochtouren, aber wenn sie etwas benötigen, das vom Betriebssystem verwaltet wird, rufen sie Hilfsroutinen auf, die vom Betriebssystem bereitgestellt werden, und dieser Code wird nicht benötigt und ist nicht in den Benutzerprogrammen selbst vorhanden. Dies beinhaltete das Schreiben auf das Display, das Speichern von Dateien, den Zugriff auf das Netzwerk usw.
Es wurden Mikrokerne geschrieben, die genau das bereitstellen, was für ein bestimmtes Programm benötigt wird, um ohne ein vollständiges Betriebssystem ausgeführt zu werden. Dies hat einige Vorteile für die erfahrenen Benutzer, während die meisten anderen verschenkt werden. Vielleicht möchten Sie die Wikipedia-Seite darüber lesen - https://en.wikipedia.org/wiki/Microkernel - wenn Sie mehr wissen möchten.
Ich habe mit einem Mikrokernel experimentiert, auf dem eine Java Virtual Machine ausgeführt werden kann, habe aber später festgestellt, dass Docker der ideale Ort dafür ist.
quelle
In typischen Desktop-Betriebssystemen ist der Kernel selbst eine ausführbare Datei. (Windows hat
ntoskrnl.exe
; Linux hatvmlinux
usw.) Wenn Sie einen Kernel benötigen, damit eine ausführbare Datei ausgeführt werden kann, können diese Betriebssysteme nicht existieren.Was Sie für einen Kernel brauchen, ist, die Dinge zu tun, die ein Kernel tut. Lassen Sie zu, dass mehrere ausführbare Dateien gleichzeitig ausgeführt werden, fechten Sie zwischen ihnen, abstrahieren Sie die Hardware usw. Die meisten Programme sind nicht in der Lage, diese Aufgaben selbst zu erledigen, und Sie möchten nicht, dass sie dies tun, selbst wenn sie könnten. In den Tagen von DOS - das selbst kaum als Betriebssystem zu bezeichnen war - verwendeten Spiele das Betriebssystem oft nur so wenig wie ein Loader und griffen direkt auf die Hardware zu, wie es ein Kernel tun würde. Aber Sie mussten oft wissen, welche Marken und Modelle von Hardware auf Ihrem Computer vorhanden waren, bevor Sie ein Spiel kauften. Viele Spiele unterstützten nur bestimmte Familien von Video- und Soundkarten und liefen bei konkurrierenden Marken sehr schlecht, wenn sie überhaupt funktionierten. Das'
quelle