Hallo,
ich versuche gerade nachzuvollziehen wie die Ausführung eines Programms
am PC funktioniert. Bei dem Szenario, was passiert, wenn ich (innerhalb
eines Betriebssystems) einen Maschinencode ausführe der direkt auf die
Hardware zugreift bin ich auf ein Problem gestoßen für das ich keine
Antwort finden kann. Eigentlich soll auf die Hardware ja über das
Betriebssystem zugegriffen werden. Die meisten Compiler werden daher
direkte Zugriffe auf die Hardware nicht zulassen.
Mal angenommen ich hätte einen Compiler zur Verfügung, der es mir
erlaubt einen Maschinenbefehl zu generieren, der z.B. direkt auf einen
I/O Pin des Prozessors zugreift. Wo, bzw. wie wird dieser böse
Maschinenbefehl abgefangen? Läuft irgendwo im Betriebssystem oder auf
der CPU eine Art Interpreter, der zulässigen Code von nicht zulässigen
unterscheidet?
Werden Programme eigentlich tatsächlich in Maschinencode abgelegt oder
gibt es da noch einmal eine Abstraktionsschicht?
TO schrieb:> Wo, bzw. wie wird dieser böse Maschinenbefehl abgefangen?
Im Prozessor selbst. Der hat mindestens 2 Modi, System und Anwendung.
Und dein böser Befehl wird vom Prozessor im Anwendungsmodus nicht
ausgeführt.
TO schrieb:> Werden Programme eigentlich tatsächlich in Maschinencode abgelegt oder> gibt es da noch einmal eine Abstraktionsschicht?
Traditionell Maschinencode. Meist werden Programme auch in Maschinencode
ausgeliefert und installiert.
In Android vor V5 gibt es eine Abstraktionsschicht für die Apps.
Programme sind als Code einer Pseudomaschine (Dalvik VM) abgelegt und
werden zur Laufzeit in Maschinencode übersetzt. Seit V5 werden sie bei
der Installation in Maschinencode übersetzt.
A. K. schrieb:> Im Prozessor selbst. Der hat mindestens 2 Modi, System und Anwendung.> Und dein böser Befehl wird vom Prozessor im Anwendungsmodus nicht> ausgeführt.
Ich hab eher etwas software-gesteuertes vermutet. Deshalb habe ich auch
keine Informationen finden können.
Wenn ich das richtig verstanden habe, dann läuft das Betriebssystem im
System-Modus und kümmert sich auch um die Verwaltung dieser Modi des
Prozessors. Beim Ausführen einer Anwendung wird dann in den
Anwendungsmodus umgeschaltet?
Ja, so eine CPU hat einen "privileged mode" und einen "user mode".
Bestimmte Instruktionen sind nur im privileged mode erlaubt. Deine
Anwendung läuft im user mode. Deshalb müssen Hardware-Treiber (zumindest
in Linux) auch quasi Kernel-Plugins sein.
>Betriebssystem zugegriffen werden. Die meisten Compiler werden daher>direkte Zugriffe auf die Hardware nicht zulassen.
Dem Compiler ist das vollkommen wurscht, was Du da diesbezüglich
programmierst. Die direkten Hardwarezugriffe werden erst zur Laufzeit
des Programms duch die CPU abgefangen, die dann via OS solche Meldungen
ungefähr wie "In der Anwendung ist ein Problem aufgetreten, und muß
beendet werden" triggern (Exception C0000005 auf Windows, SigSegV bzw
Signal 11 unter UniX/Linux).
Kannst Dir ja mal folgendes zu Gemüte führen, denn dort werden die
Privilegien bzw. Ringe geregelt:
https://de.wikipedia.org/wiki/Ring_%28CPU%29
Hallo
Ich sehe nur die Möglichkeit, passende Treiber zu programmieren, dabei
kommt ein Großteil des Programmes in den Treiber, oder man verwendet ein
Betriebssystem ohne Protected Mode bzw. Protection, oder man
programmiert ohne Betriebssystem.
Bei Windows gibt es universelle Treiber für I/O Zugriffe, aber ob die
was taugen, Geschwindigkeit usw.., weiß ich nicht.
MfG
Naja. Hardwaere beinhaltet eigene Protokolle. Einige sind spezifiziert,
wie zB das SATA, andere ein Wenig, dafuer plus Herstellererweiterungen.
Wie zB die Grafikkarten.
Ein Diskcontroller besteht also aus dem Interface zur Disk, genannt
SATA, und einem Businterface, definiert durch den Diskcontroller
Hersteller. Wie man nun diesen controller in das Betriebssystem
einbindet macht also der Diskcontroller Treiber, geschrieben vom
Diskcontroller Hersteller. Dieser Treiber kann also Sektoren lesen und
Schreiben, so etwa. Dann benoetigt man noch einen Filesystem Treiber,
vom Betriebssystem. zB fuer NTFS von windows. oder Ext2, Ext3, Ext4 bei
Linux.
Matthias K. schrieb:> passende Treiber zu programmieren, dabei> kommt ein Großteil des Programmes in den Treiber
Nein, das ist ein kapitaler Fehler. Der Treiber soll so einfach wie
möglich programmiert werden und nur das Nötigste enthalten, um die
Hardware zu bedienen. U.a. deshalb, weil ein Treiber privilegiert genug
ist, das ganze System zum Stillstand zu bringen, er darf daher keine
Warteschleifen enthalten oder länger laufende Operationen. Das heisst
nicht, dass das immer eingehalten wird, es gibt auch unter Windows oder
Linux Gelegenheiten, wo man einige Zeit eine Sanduhr sieht und das
System nicht mehr reagiert, aber eigentlich darf das nicht passieren.
Wenn du z.B. eine Relaiskarte ansteuern willst, dann gehört in den
Treiber die Ausgabe eines Bytes an den I/O-Port, allerhöchstens kann man
noch im Treiber Funktionen unterbringen, um ein einzelnes Relais zu
schalten. Alles andere gehört ins (User) Anwendungsprogramm.
Georg
TO schrieb:> Wo, bzw. wie wird dieser böse> Maschinenbefehl abgefangen?
Es werden nicht die Befehle abgefangen, sondern es werden die Adressen
durch die Memory Protection Unit (MPU) geprüft. Die User-Applikation
kriegt einen bestimmten Memory-Bereich zugewiesen. Versucht sie Zugriffe
außerhalb des Bereichs, gibt es eine Exception.
Z.B. konnte man noch bis Windows-XP direkt auf die COM1 (Adresse 0x3F8)
zugreifen. Die Exception hat dann eine original 16550 UART emuliert und
das ging sogar, wenn die UART am USB hing.
Ich hab leider viel davon vergessen. Ich empfehl das iApx386 User manual
von Intel. Es gibt Trap Gates, die bilden das Interface zwischen den
verschiedenen Schichten.
Zum einen gibt es privilegierten Code, der laeft im Ring 0, das sind zB
Treiber. User Code laeuft im Ring 3, und das Betriebssystem laeuft im
Ring 2. Wenn zB ein Sprung auf nichtexistierendes Memory ausgefuehrt
werden soll, wird dieser Code von der Platte oder so nachgeladen. Wenn
eine nicht existierende RAM Adresse gelesen/geschrieben werden soll,
wird diese Memory Seite angelegt, resp geswappt. Interrupts gehen durch
ein Interrupt Gate, dort werden die Interrupts virtualisiert. IO
Zugriffe gehen durch ein anderes Gate, dort werden die Rechte geprueft.
Memory Segmente haben jeweils Zugriffsrechte. Ein User Programm darf zB
nie in ein Codesegment schreiben. User Code darf auch nicht ins RAM des
Betriebssystems schreiben. Wenn das trotzdem der Fall sein sollte, wird
das auch durch ein Gate erledigt. Shared Memory wird zB so verwaltet.
Peter D. schrieb:> Es werden nicht die Befehle abgefangen,
Doch. Beides. Es werden vom Prozessor privilegierte Befehle abgefangen,
beispielsweise enable/disable Interrupt, und es werden Speicherzugriffe
kontrolliert.
Oh D. schrieb:> Ich empfehl das iApx386 User manual von Intel.
Ich nicht. Die bizarre Komplexität des 386 in dieser Frage geht
erheblich über das hinaus, was für das Verständnis der Grundlagen
erforderlich ist und ist eher historisch interessant als für heutige
Verhältnisse wesentlich.
Diese Komplexität war übertrieben. Das ganze Gedödel mit Call-, Bill-,
Trap-, Interrupt- und Task-Gates war nett gedacht, wurde aber kaum
jemals so genutzt wie vorgesehen. In der 64-Bit x86 Architektur wurde
das zusammen mit anderen Aspekten der Segmentierung stark eingeschrumpft
und daran orientiert, was man tatsächlich benötigt. Nicht mehr an den
feuchten Träumen aus sehr CISC-lastigen 80ern.
Ein Beispiel dafür stellen die SYSCALL/SYSENTER-Befehle dar, die den
ganzen Segment/Gate-Kram links liegen lassen.
Ich denke, man sollte sich für die Grundlagen eher an der Architektur
der Cortex A Prozessoren von ARM orientieren.