Linux-Kernel-Space und User-Space

7

Ich bin verwirrt darüber, wie genau Kernel und Benutzerraum strukturiert sind und welche Teile des Speichers belegt sind. Mein gegenwärtiges (möglicherweise falsches) Verständnis ist das:

  1. Es wird ein Prozess erstellt und der virtuelle Speicher dieses Prozesses wird in einen User-Space und einen Kernel-Space-Bereich aufgeteilt, wobei der User-Space-Bereich Daten, Code, Stack, Heap usw. des Prozesses enthält und der Kernel-Space-Bereich enthält Dinge wie die Seitentabelle für den Prozess und Kernel-Code. Ich bin nicht sicher, was der Kernel-Code wäre ... Treibercode oder ähnliches?

  2. Ist die Systemaufruf-Tabelle immer der gleichen Region im Kernel-Space eines Prozesses zugeordnet? (Ist es sogar richtig, "Kernel-Raum eines Prozesses" zu sagen?

  3. Wenn ich meinen eigenen Treiber / Modul schreibe und es einfüge, wird dieser Treibercode dann automatisch in den Kernel-Space jedes neuen Prozesses kopiert, der erstellt wird? Wenn nicht ... wie genau funktioniert das?

Vielen Dank im Voraus für jede Eingabe, Literatur / Links, die helfen können, meine Fragen zu klären, sind ebenfalls in Ordnung.

Prost, Ziegelstein

    
user2239930 20.06.2013, 08:21
quelle

2 Antworten

27

Sie haben die allgemeine Idee meistens richtig, aber machen Sie diese Anpassung: Es gibt nur einen "Kernraum" für die gesamte Maschine, und alle Prozesse teilen ihn.

Wenn ein Prozess aktiv ist, kann er entweder im "Benutzermodus" oder im "Kernelmodus" ausgeführt werden.

Im Benutzermodus befinden sich die Anweisungen, die von der CPU ausgeführt werden, auf der Seite des Benutzerspeichers der Speicherzuordnung. Das Programm führt seinen eigenen Code oder Code aus einer Benutzerbereichs-Bibliothek aus. Im Benutzermodus hat ein Prozess eingeschränkte Fähigkeiten. In der CPU gibt es ein Flag, das besagt, dass keine privilegierten Befehle verwendet werden dürfen, und auf den Kernelspeicher kann nicht zugegriffen werden, obwohl er in der Speicherzuordnung des Prozesses vorhanden ist. (Sie würden nicht wollen, dass irgendein Programm nur den Speicher des Kernels liest und schreibt - alle Sicherheit wäre weg.)

Wenn ein Prozess etwas anderes tun möchte als Daten in seinem eigenen virtuellen Speicher (Benutzerbereich) zu verschieben, wie zum Beispiel eine Datei öffnen, muss er einen Syscall machen. Jede CPU-Architektur hat ihre eigene einzigartige Methode, Syscalls zu erstellen, aber sie laufen alle darauf hinaus: Eine magische Anweisung wird ausgeführt, die CPU schaltet das Flag "privilegierter Modus" ein und springt zu einer speziellen Adresse im Kernel-Bereich, dem "syscall Einstiegspunkt ".

Jetzt läuft der Prozess im Kernel-Modus. Auszuführende Befehle befinden sich im Kernel-Speicher und können beliebigen Speicher lesen und schreiben. Der Kernel prüft die Anfrage, die der Prozess gerade gemacht hat und entscheidet, was damit zu tun ist.

Im Beispiel open erhält der Kernel 2 oder 3 Parameter, die den Argumenten von int open(const char *filename, int flags[, int mode]) entsprechen. Das erste Argument gibt ein Beispiel dafür, wann Kernelspace Zugriff auf den Benutzerbereich benötigt. Sie haben open("foo", O_RDONLY) angegeben, so dass die Zeichenfolge "foo" Teil Ihres Programms im Benutzerbereich ist. Der Syscall-Mechanismus hat nur einen Zeiger und keine Zeichenfolge übergeben, daher muss der Kernel die Zeichenfolge aus dem Benutzerspeicher lesen.

Um die angeforderte Datei zu finden, kann der Kernel Dateisystemtreiber (um herauszufinden, wo sich die Datei befindet) und Gerätetreiber (um die erforderlichen Blöcke vom Datenträger zu laden) oder Netzwerkgerätetreiber und Protokolle (von denen die Datei geladen wird) blockieren eine entfernte Quelle). All diese Dinge sind Teil des Kernels, d. H. Im Kernelspace, unabhängig davon, ob sie eingebaut sind oder als Module geladen wurden.

Wenn die Anfrage nicht sofort erfüllt werden kann, kann der Kernel den Prozess in den Ruhezustand versetzen. Das bedeutet, dass der Prozess von der CPU genommen wird, bis eine Antwort von der Festplatte oder dem Netzwerk empfangen wird. Ein anderer Prozess kann jetzt eine Chance erhalten. Später, wenn die Antwort eintrifft, wird der Prozess erneut gestartet (immer noch im Kernel-Modus). Jetzt, da die Datei gefunden wurde, kann der open syscall beendet werden (überprüfen Sie die Berechtigungen, erstellen Sie einen Dateideskriptor) und kehren Sie zum Benutzerbereich zurück.

Die Rückkehr in den Benutzerbereich ist eine einfache Angelegenheit, die CPU in den nicht-privilegierten Modus zurückzuversetzen und die Register vor dem Übergang des Benutzer- & gt; -Kernels wiederherzustellen, wobei der Befehlszeiger auf den Befehl nach der magischen syscall-Anweisung zeigt .

Neben syscalls gibt es noch andere Dinge, die einen Übergang vom Benutzermodus zum Kernelmodus verursachen können, einschließlich:

  1. Seitenfehler - Wenn Ihr Prozess auf eine virtuelle Speicheradresse zugreift, der keine physikalische Adresse zugewiesen ist, wechselt die CPU in den Kernel-Modus und springt zum Seitenfehler-Handler. Der Kernel entscheidet dann, ob die virtuelle Adresse gültig ist oder nicht, und er erstellt entweder eine physische Seite und setzt den Prozess in dem Benutzerbereich fort, in dem er aufgehört hat, oder sendet einen SIGSEGV.
  2. unterbricht - einige Hardware (Netzwerk, Festplatte, serielle Schnittstelle usw.) benachrichtigt die CPU, dass sie Aufmerksamkeit benötigt. Die CPU tritt in den Kernel-Modus ein und springt zu einem Handler, der Kernel antwortet darauf und nimmt dann den Userspace-Prozess wieder auf, der vor dem Interrupt lief.

Das Laden eines Moduls erfolgt mit einem Syscall, der den Kernel auffordert, den Code und die Daten des Moduls in den Kernel-Bereich zu kopieren und seinen Initialisierungscode im Kernel-Modus auszuführen.

Das ist ziemlich lang, also höre ich auf. Ich hoffe, dass die durchgängige Fokussierung auf User-Kernel-Übergänge genügend Beispiele geliefert hat, um die Idee zu festigen.

    
Wumpus Q. Wumbley 21.06.2013, 03:16
quelle
2

Es gibt keine Kernel-Space-Region in der virtuellen Speicherzuordnung des Prozesses. Die virtuelle Speicherzuordnung enthält: text, bss, data, heap, stack des geladenen Programms und shared libs. Unter Linux können Sie / proc / $ PID / maps eines beliebigen User-Space-Prozesses für ein Beispiel überprüfen.

Wenn ein User-Space-Prozess über einen Systemaufruf auf einen Kernel-Domain-Code zugreift, wird der Kernel-Code im Namen des Prozesses in seinem Stack ausgeführt. Offensichtlich ist nach dem Zurückrufen des Systemaufrufs der gesamte Kernel / Treiber-Code außerhalb des Stacks. Um zu verdeutlichen, dass zu einem bestimmten Zeitpunkt ein Teil des Kernel-Codes von keinem Prozess verwendet wird, ist er nicht Teil der virtuellen Speicherzuordnung eines Prozesses.

Wenn Sie Linux verwenden, würde ich das Buch "Linux-Kernel-Entwicklung" von Robert Love empfehlen.

    
srd 20.06.2013 20:36
quelle

Tags und Links