Was ist der Unterschied zwischen Benutzer- und Kernel-Modus in Betriebssystemen?


104

Was sind die Unterschiede zwischen dem Benutzermodus und dem Kernelmodus, warum und wie aktivieren Sie einen von beiden und welche Anwendungsfälle gibt es?



1
@ CiroSantilli709 question 抓捕 六四 事件 法轮功 Eine Frage, die vor 7 Jahren gestellt wurde, kann nicht als Duplikat für eine vor 6 Jahren gestellte Frage geschlossen werden. Wenn es sich wirklich um Duplikate handelt, sollte der Verschluss umgekehrt sein.
Salvador Dali

2
@SalvadorDali Hallo, der aktuelle Konsens besteht darin, durch "Qualität" zu schließen: meta.stackexchange.com/questions/147643/… Da "Qualität" nicht messbar ist, gehe ich einfach durch Upvotes. ;-) Wahrscheinlich kommt es darauf an, welche Frage die besten neuen Google-Keywords im Titel trifft. Ich ermutige Sie, Ihre Antwort dort einfach mit einem unten hinzugefügten Haftungsausschluss zu kopieren und von diesem zu verlinken, falls er geschlossen wird.
Ciro Santilli 法轮功 冠状 病 六四 事件 19

Antworten:


143
  1. 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.

  2. 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

Grundlegendes zum Benutzer- und Kernelmodus


Frage mich, in welchem ​​Modus sich der Prozessor befindet, wenn auf der CPU Betriebssystemcode ausgeführt wird?
JackieLam

2
@JackieLam: Es sollte sich im Kernel-Modus befinden.
Kadina

Also per se, um einen User-Space- Prozess auszuführen , muss er dem Kernel-Space zugeordnet werden ?
Roottraveller

@rahul Ich bezweifle, dass der Referenzspeicher im Benutzermodus abgerufen werden kann oder dass die einfachste Datenbearbeitung zu einem teuren Moduswechsel in einer Sprache wie Java führt.
Maki XIE

48

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:

  • Modus, in dem alle Benutzerprogramme ausgeführt werden. Es hat keinen Zugriff auf RAM und Hardware. Der Grund dafür ist, dass alle Programme, die im Kernelmodus ausgeführt werden, den Speicher des anderen überschreiben könnten. Wenn auf eine dieser Funktionen zugegriffen werden muss, wird die zugrunde liegende API aufgerufen. Jeder von Windows gestartete Prozess mit Ausnahme des Systemprozesses wird im Benutzermodus ausgeführt.

Kernel-Modus:

  • Modus, in dem alle Kernel-Programme ausgeführt werden (verschiedene Treiber). Es hat Zugriff auf jede Ressource und zugrunde liegende Hardware. Jeder CPU-Befehl kann ausgeführt werden und auf jede Speicheradresse kann zugegriffen werden. Dieser Modus ist Treibern vorbehalten, die auf der untersten Ebene arbeiten

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

http://en.wikipedia.org/wiki/Direct_memory_access

http://en.wikipedia.org/wiki/Interrupt_request


Frage mich, in welchem ​​Modus sich der Prozessor befindet, wenn auf der CPU Betriebssystemcode ausgeführt wird?
JackieLam

1
@ JackieLam: Kernel-Modus
Apurv Nerlekar

10

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.

Kommunikation zwischen Benutzermodus und Kernelmodus


6

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:

  • 0 für Kernel
  • 3 für Benutzer

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 = 0Dies 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 inund ausführen und outverfü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 0x80odersyscall 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
    

    GitHub stromaufwärts .

    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 execSystemaufruf 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:

  • Es ist einfacher, Programme zu erstellen, da Sie sicherer sind, dass eines das andere nicht stört. Beispielsweise muss sich ein Userland-Prozess nicht darum kümmern, den Speicher eines anderen Programms aufgrund von Paging zu überschreiben oder die Hardware für einen anderen Prozess in einen ungültigen Zustand zu versetzen.
  • es ist sicherer. Beispielsweise können Dateiberechtigungen und Speichertrennung verhindern, dass eine Hacking-App Ihre Bankdaten liest. Dies setzt natürlich voraus, dass Sie dem Kernel vertrauen.

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 svcAnweisung (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
    

    GitHub stromaufwärts .

    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 hvcAnweisung (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 smcAnweisung (Secure Mode Call)

Das ARMv8-Architekturreferenzmodell DDI 0487C.a - Kapitel D1 - Das Programmierermodell auf AArch64-Systemebene - Abbildung D1-1 veranschaulicht dies auf wunderbare Weise:

Geben Sie hier die Bildbeschreibung ein

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:

Geben Sie hier die Bildbeschreibung ein

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 MRSAnweisung 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.


1
Da diese Frage für kein Betriebssystem spezifisch ist inund outfü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.
Michael Petch

Natürlich setzen Sie die IOPL-Bits auf den Wert 3, dann hat das Ring 3-Programm vollen Portzugriff und die TSS-E / A-Berechtigungen gelten nicht.
Michael Petch

@ MichaelPetch danke, das wusste ich nicht. Ich habe die Antwort aktualisiert.
Ciro Santilli 法轮功 冠状 病 六四 事件 21

5

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 .


2
Dies ist für Sie als Programmierer wichtig, da Kernel-Bugs weitaus schlimmeres Chaos anrichten, als Sie es vielleicht gewohnt sind. Ein Grund für die Unterscheidung zwischen Kernel und Benutzer besteht darin, dass der Kernel kritische Systemressourcen überwachen / steuern und jeden Benutzer vor den anderen schützen kann. Es ist etwas vereinfacht, aber dennoch hilfreich, sich daran zu erinnern, dass Benutzerfehler oft ärgerlich sind, aber Kernel-Fehler dazu neigen, den gesamten Computer herunterzufahren.
Adam Liss

3

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.


2

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:

  • Schutz von Benutzerprogrammen vor dem Zugriff auf den gesamten Speicher, damit Programme das Betriebssystem nicht überschreiben, z.
  • Verhindern, dass Benutzerprogramme vertrauliche Anweisungen ausführen, z. B. solche, die die Grenzen des CPU-Speicherzeigers ändern, damit Programme beispielsweise ihre Speichergrenzen nicht überschreiten.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.