Was sind die Unterschiede zwischen dem Benutzermodus und dem Kernelmodus, warum und wie aktivieren Sie einen von beiden und welche Anwendungsfälle gibt es?
Was sind die Unterschiede zwischen dem Benutzermodus und dem Kernelmodus, warum und wie aktivieren Sie einen von beiden und welche Anwendungsfälle gibt es?
Antworten:
Kernel-Modus
Im Kernel-Modus hat der ausführende Code vollständigen und uneingeschränkten Zugriff auf die zugrunde liegende Hardware. Es kann jeden CPU-Befehl ausführen und auf jede Speicheradresse verweisen. Der Kernelmodus ist im Allgemeinen für die niedrigsten und vertrauenswürdigsten Funktionen des Betriebssystems reserviert. Abstürze im Kernel-Modus sind katastrophal. Sie werden den gesamten PC anhalten.
Benutzermodus
Im Benutzermodus kann der ausführende Code nicht direkt auf Hardware oder Referenzspeicher zugreifen. Code, der im Benutzermodus ausgeführt wird, muss an System-APIs delegiert werden, um auf Hardware oder Speicher zugreifen zu können. Aufgrund des Schutzes, den diese Art der Isolation bietet, können Abstürze im Benutzermodus immer wiederhergestellt werden. Der größte Teil des auf Ihrem Computer ausgeführten Codes wird im Benutzermodus ausgeführt.
Weiterlesen
Dies sind zwei verschiedene Modi, in denen Ihr Computer arbeiten kann. Zuvor, wenn Computer wie ein großer Raum waren, wenn etwas abstürzt, wird der gesamte Computer angehalten. Computerarchitekten beschließen daher, dies zu ändern. Moderne Mikroprozessoren implementieren in Hardware mindestens 2 verschiedene Zustände.
Benutzermodus:
Kernel-Modus:
Wie der Wechsel erfolgt.
Der Wechsel vom Benutzermodus in den Kernelmodus erfolgt nicht automatisch durch die CPU. Die CPU wird durch Interrupts (Timer, Tastatur, E / A) unterbrochen. Wenn ein Interrupt auftritt, beendet die CPU die Ausführung des aktuell ausgeführten Programms, wechselt in den Kernelmodus und führt den Interrupt-Handler aus. Dieser Handler speichert den Status der CPU, führt seine Operationen aus, stellt den Status wieder her und kehrt in den Benutzermodus zurück.
http://en.wikibooks.org/wiki/Windows_Programming/User_Mode_vs_Kernel_Mode
http://tldp.org/HOWTO/KernelAnalysis-HOWTO-3.html
Ein Prozessor in einem Computer unter Windows verfügt über zwei verschiedene Modi: Benutzermodus und Kernelmodus. Der Prozessor wechselt zwischen den beiden Modi, je nachdem, welcher Codetyp auf dem Prozessor ausgeführt wird. Anwendungen werden im Benutzermodus ausgeführt, und Kernkomponenten des Betriebssystems werden im Kernelmodus ausgeführt. Während viele Treiber im Kernelmodus ausgeführt werden, werden einige Treiber möglicherweise im Benutzermodus ausgeführt.
Wenn Sie eine Anwendung im Benutzermodus starten, erstellt Windows einen Prozess für die Anwendung. Der Prozess stellt der Anwendung einen privaten virtuellen Adressraum und eine private Handle-Tabelle zur Verfügung. Da der virtuelle Adressraum einer Anwendung privat ist, kann eine Anwendung keine Daten ändern, die zu einer anderen Anwendung gehören. Jede Anwendung wird isoliert ausgeführt. Wenn eine Anwendung abstürzt, ist der Absturz auf diese eine Anwendung beschränkt. Andere Anwendungen und das Betriebssystem sind vom Absturz nicht betroffen.
Der virtuelle Adressraum einer Anwendung im Benutzermodus ist nicht nur privat, sondern auch begrenzt. Ein Prozessor, der im Benutzermodus ausgeführt wird, kann nicht auf virtuelle Adressen zugreifen, die für das Betriebssystem reserviert sind. Durch die Einschränkung des virtuellen Adressraums einer Anwendung im Benutzermodus wird verhindert, dass die Anwendung kritische Betriebssystemdaten ändert und möglicherweise beschädigt.
Der gesamte Code, der im Kernelmodus ausgeführt wird, teilt sich einen einzelnen virtuellen Adressraum. Dies bedeutet, dass ein Kernel-Modus-Treiber nicht von anderen Treibern und dem Betriebssystem selbst isoliert ist. Wenn ein Treiber im Kernelmodus versehentlich an die falsche virtuelle Adresse schreibt, können Daten, die zum Betriebssystem oder zu einem anderen Treiber gehören, gefährdet werden. Wenn ein Kernel-Modus-Treiber abstürzt, stürzt das gesamte Betriebssystem ab.
Wenn Sie ein Windows-Benutzer sind, gehen Sie einmal über diesen Link, um mehr zu erhalten.
CPU-Ringe sind die klarste Unterscheidung
Im x86-geschützten Modus befindet sich die CPU immer in einem von 4 Ringen. Der Linux-Kernel verwendet nur 0 und 3:
Dies ist die schwierigste und schnellste Definition von Kernel vs. Userland.
Warum verwendet Linux die Ringe 1 und 2 nicht: CPU-Berechtigungsringe: Warum werden die Ringe 1 und 2 nicht verwendet?
Wie wird der aktuelle Ring ermittelt?
Der aktuelle Ring wird durch eine Kombination von:
Globale Deskriptortabelle: Eine speicherinterne Tabelle mit GDT-Einträgen, und jeder Eintrag verfügt über ein Feld Privl
, das den Ring codiert.
Der LGDT-Befehl setzt die Adresse auf die aktuelle Deskriptortabelle.
Siehe auch: http://wiki.osdev.org/Global_Descriptor_Table
Das Segment registriert CS, DS usw., die auf den Index eines Eintrags in der GDT verweisen.
CS = 0
Dies bedeutet beispielsweise, dass der erste Eintrag des GDT derzeit für den ausführenden Code aktiv ist.
Was kann jeder Ring?
Der CPU-Chip ist physisch so aufgebaut, dass:
Ring 0 kann alles
Ring 3 kann nicht mehrere Anweisungen ausführen und in mehrere Register schreiben, insbesondere:
kann seinen eigenen Ring nicht ändern! Andernfalls könnte es sich auf Ring 0 setzen und Ringe wären nutzlos.
Mit anderen Worten, der aktuelle Segmentdeskriptor , der den aktuellen Ring bestimmt , kann nicht geändert werden .
Die Seitentabellen können nicht geändert werden: Wie funktioniert x86-Paging?
Mit anderen Worten, das CR3-Register kann nicht geändert werden, und das Paging selbst verhindert das Ändern der Seitentabellen.
Dies verhindert, dass ein Prozess aus Sicherheits- / Programmiergründen den Speicher anderer Prozesse sieht.
Interrupt-Handler können nicht registriert werden. Diese werden durch Schreiben in Speicherorte konfiguriert, was auch durch Paging verhindert wird.
Handler werden in Ring 0 ausgeführt und würden das Sicherheitsmodell beschädigen.
Mit anderen Worten, kann die LGDT- und LIDT-Anweisungen nicht verwenden.
kann keine E / A-Anweisungen wie in
und ausführen und out
verfügt daher über beliebige Hardwarezugriffe.
Andernfalls wären beispielsweise Dateiberechtigungen nutzlos, wenn ein Programm direkt von der Festplatte lesen könnte.
Genauer gesagt dank Michael Petch : Es ist dem Betriebssystem tatsächlich möglich, E / A-Anweisungen auf Ring 3 zuzulassen, dies wird tatsächlich vom Task- Statussegment gesteuert .
Was nicht möglich ist, ist, dass Ring 3 sich selbst die Erlaubnis dazu gibt, wenn er es überhaupt nicht hatte.
Linux verbietet es immer. Siehe auch: Warum verwendet Linux den Hardware-Kontextschalter nicht über das TSS?
Wie wechseln Programme und Betriebssysteme zwischen Ringen?
Wenn die CPU eingeschaltet ist, startet sie das erste Programm in Ring 0 (gut, aber es ist eine gute Annäherung). Sie können sich dieses anfängliche Programm als den Kernel vorstellen (aber normalerweise ist es ein Bootloader, der den Kernel dann noch in Ring 0 aufruft ).
Wenn ein Userland-Prozess möchte, dass der Kernel etwas dafür tut, z. B. in eine Datei schreiben, verwendet er eine Anweisung, die einen Interrupt generiert, z. B. int 0x80
odersyscall
um den Kernel zu signalisieren. x86-64 Linux Syscall Hallo Welt Beispiel:
.data
hello_world:
.ascii "hello world\n"
hello_world_len = . - hello_world
.text
.global _start
_start:
/* write */
mov $1, %rax
mov $1, %rdi
mov $hello_world, %rsi
mov $hello_world_len, %rdx
syscall
/* exit */
mov $60, %rax
mov $0, %rdi
syscall
kompilieren und ausführen:
as -o hello_world.o hello_world.S
ld -o hello_world.out hello_world.o
./hello_world.out
In diesem Fall ruft die CPU einen Interrupt-Callback-Handler auf, den der Kernel beim Booten registriert hat. Hier ist ein konkretes Baremetall-Beispiel, das einen Handler registriert und verwendet .
Dieser Handler wird in Ring 0 ausgeführt, der entscheidet, ob der Kernel diese Aktion zulässt, die Aktion ausführt und das Userland-Programm in Ring 3 neu startet. X86_64
Wenn der exec
Systemaufruf verwendet wird (oder wenn der Kernel gestartet wird/init
), bereitet der Kernel die Register und den Speicher des neuen Userland-Prozesses vor, springt dann zum Einstiegspunkt und schaltet die CPU auf Ring 3
Wenn das Programm versucht, etwas Unartiges wie das Schreiben in ein verbotenes Register oder eine Speicheradresse (aufgrund von Paging) zu tun, ruft die CPU auch einen Kernel-Callback-Handler in Ring 0 auf.
Aber da das Benutzerland ungezogen war, könnte der Kernel den Prozess dieses Mal beenden oder ihm eine Warnung mit einem Signal geben.
Wenn der Kernel startet, richtet er eine Hardware-Uhr mit einer festen Frequenz ein, die regelmäßig Interrupts erzeugt.
Diese Hardware-Uhr generiert Interrupts, die Ring 0 ausführen, und ermöglicht es ihr, zu planen, welche Userland-Prozesse aufgeweckt werden sollen.
Auf diese Weise kann die Planung auch dann erfolgen, wenn die Prozesse keine Systemaufrufe ausführen.
Was bringt es, mehrere Ringe zu haben?
Die Trennung von Kernel und Userland bietet zwei Hauptvorteile:
Wie kann man damit herumspielen?
Ich habe ein Bare-Metal-Setup erstellt, mit dem sich Ringe direkt manipulieren lassen: https://github.com/cirosantilli/x86-bare-metal-examples
Ich hatte leider nicht die Geduld, ein Userland-Beispiel zu erstellen, aber ich ging so weit wie das Paging-Setup, sodass Userland machbar sein sollte. Ich würde gerne eine Pull-Anfrage sehen.
Alternativ werden Linux-Kernelmodule in Ring 0 ausgeführt, sodass Sie damit privilegierte Operationen ausprobieren können, z. B. die Steuerregister lesen: Wie kann man von einem Programm aus auf die Steuerregister cr0, cr2, cr3 zugreifen? Segmentierungsfehler erhalten
Hier ist ein praktisches QEMU + Buildroot-Setup, mit dem Sie es ausprobieren können, ohne Ihren Host zu töten.
Der Nachteil von Kernelmodulen ist, dass andere kthreads ausgeführt werden und Ihre Experimente beeinträchtigen können. Theoretisch können Sie jedoch alle Interrupt-Handler mit Ihrem Kernelmodul übernehmen und das System besitzen, das wäre eigentlich ein interessantes Projekt.
Negative Ringe
Während im Intel-Handbuch nicht auf negative Ringe verwiesen wird, gibt es tatsächlich CPU-Modi, die über weitere Funktionen als Ring 0 selbst verfügen und daher gut zum Namen "negativer Ring" passen.
Ein Beispiel ist der in der Virtualisierung verwendete Hypervisor-Modus.
Für weitere Details siehe:
ARM
In ARM werden die Ringe stattdessen als Ausnahmeebenen bezeichnet, aber die Hauptideen bleiben dieselben.
In ARMv8 gibt es 4 Ausnahmestufen, die häufig verwendet werden als:
EL0: Benutzerland
EL1: Kernel ("Supervisor" in der ARM-Terminologie).
Eingetragen mit der svc
Anweisung (SuperVisor Call), die zuvor als swi
vor der einheitlichen Assembly bekannt war. Diese Anweisung wird zum Ausführen von Linux-Systemaufrufen verwendet. Hallo Welt ARMv8 Beispiel:
hallo.S
.text
.global _start
_start:
/* write */
mov x0, 1
ldr x1, =msg
ldr x2, =len
mov x8, 64
svc 0
/* exit */
mov x0, 0
mov x8, 93
svc 0
msg:
.ascii "hello syscall v8\n"
len = . - msg
Testen Sie es mit QEMU unter Ubuntu 16.04:
sudo apt-get install qemu-user gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-as -o hello.o hello.S
arm-linux-gnueabihf-ld -o hello hello.o
qemu-arm hello
Hier ist ein konkretes Baremetall-Beispiel, das einen SVC-Handler registriert und einen SVC-Aufruf ausführt .
EL2: Hypervisoren , zum Beispiel Xen .
Eingetragen mit der hvc
Anweisung (HyperVisor Call).
Ein Hypervisor ist für ein Betriebssystem das, was ein Betriebssystem für das Benutzerland ist.
Mit Xen können Sie beispielsweise mehrere Betriebssysteme wie Linux oder Windows gleichzeitig auf demselben System ausführen und die Betriebssysteme aus Sicherheits- und Debug-Gründen voneinander isolieren, genau wie Linux dies für Userland-Programme tut.
Hypervisoren sind ein wichtiger Bestandteil der heutigen Cloud-Infrastruktur: Sie ermöglichen die Ausführung mehrerer Server auf einer einzigen Hardware, halten die Hardware-Auslastung immer nahe 100% und sparen viel Geld.
AWS beispielsweise verwendete Xen bis 2017, als der Wechsel zu KVM die Nachricht verbreitete .
EL3: noch ein Level. TODO Beispiel.
Eingetragen mit der smc
Anweisung (Secure Mode Call)
Das ARMv8-Architekturreferenzmodell DDI 0487C.a - Kapitel D1 - Das Programmierermodell auf AArch64-Systemebene - Abbildung D1-1 veranschaulicht dies auf wunderbare Weise:
Die ARM-Situation hat sich mit dem Aufkommen von ARMv8.1 Virtualization Host Extensions (VHE) ein wenig geändert . Mit dieser Erweiterung kann der Kernel effizient in EL2 ausgeführt werden:
VHE wurde entwickelt, weil In-Linux-Kernel-Virtualisierungslösungen wie KVM gegenüber Xen an Boden gewonnen haben (siehe z. B. die oben erwähnte Umstellung von AWS auf KVM), da die meisten Clients nur Linux-VMs benötigen und, wie Sie sich vorstellen können, alles in einem einzigen sind Projekt ist KVM einfacher und möglicherweise effizienter als Xen. In diesen Fällen fungiert nun der Linux-Kernel des Hosts als Hypervisor.
Beachten Sie, dass ARM, möglicherweise aufgrund des Vorteils der Rückschau, eine bessere Namenskonvention für die Berechtigungsstufen als x86 hat, ohne dass negative Stufen erforderlich sind: 0 ist die niedrigere und 3 die höchste. Höhere Ebenen werden in der Regel häufiger erstellt als niedrigere.
Die aktuelle EL kann mit der MRS
Anweisung abgefragt werden : Was ist der aktuelle Ausführungsmodus / Ausnahmestufe usw.?
ARM erfordert nicht, dass alle Ausnahmestufen vorhanden sind, um Implementierungen zu ermöglichen, bei denen die Funktion zum Speichern des Chipbereichs nicht erforderlich ist. ARMv8 "Ausnahmestufen" sagt:
Eine Implementierung enthält möglicherweise nicht alle Ausnahmestufen. Alle Implementierungen müssen EL0 und EL1 enthalten. EL2 und EL3 sind optional.
QEMU ist zum Beispiel standardmäßig EL1, aber EL2 und EL3 können mit Befehlszeilenoptionen aktiviert werden: qemu-system-aarch64 gibt el1 ein, wenn a53 eingeschaltet wird
Code-Snippets, die unter Ubuntu 18.10 getestet wurden.
in
und out
für Ring 3 verfügbar ist, kann der TSS auf eine E / A-Berechtigungstabelle in der aktuellen Task verweisen, die Lese- / Schreibzugriff auf alle oder bestimmte Ports gewährt.
Ich werde einen Stich in die Dunkelheit machen und vermuten, dass Sie über Windows sprechen. Kurz gesagt, der Kernel-Modus hat vollen Zugriff auf Hardware, der Benutzermodus jedoch nicht. Beispielsweise werden viele, wenn nicht die meisten Gerätetreiber im Kernelmodus geschrieben, weil sie feinere Details ihrer Hardware steuern müssen.
Siehe auch dieses Wikibook .
Andere Antworten erklärten bereits den Unterschied zwischen Benutzer- und Kernelmodus. Wenn Sie wirklich ins Detail gehen möchten, sollten Sie eine Kopie von Windows Internals erhalten , einem hervorragenden Buch von Mark Russinovich und David Solomon, in dem die Architektur und die Innendetails der verschiedenen Windows-Betriebssysteme beschrieben werden.
Was
Grundsätzlich ist der Unterschied zwischen Kernel- und Benutzermodus nicht betriebssystemabhängig und wird nur dadurch erreicht, dass einige Anweisungen eingeschränkt werden, die nur im Kernelmodus mittels Hardware-Design ausgeführt werden sollen. Alle anderen Zwecke wie der Speicherschutz können nur durch diese Einschränkung ausgeführt werden.
Wie
Dies bedeutet, dass der Prozessor entweder im Kernelmodus oder im Benutzermodus lebt. Mithilfe einiger Mechanismen kann die Architektur sicherstellen, dass bei jedem Wechsel in den Kernelmodus der Betriebssystemcode zum Ausführen abgerufen wird.
Warum
Mit dieser Hardware-Infrastruktur könnten diese in gängigen Betriebssystemen erreicht werden: