Heim >Betrieb und Instandhaltung >Betrieb und Wartung von Linux >Detaillierte Erläuterung des Linux-Benutzerraums und des Kernelraums

Detaillierte Erläuterung des Linux-Benutzerraums und des Kernelraums

藏色散人
藏色散人nach vorne
2020-12-08 17:01:104373Durchsuche

Empfohlen: „Linux-Video-Tutorial

1. Einführung

  • Linux-Betriebssystem und -Treiber werden im Kernel-Bereich ausgeführt, und Anwendungen werden im Benutzerbereich ausgeführt. Die beiden können nicht einfach Zeiger zum Übertragen von Daten verwenden. Aufgrund des von Linux verwendeten virtuellen Speichermechanismus können Benutzerbereichsdaten ausgelagert werden, wenn der Kernelbereich Benutzerbereichszeiger verwendet. Die Speicherzuordnung des Benutzerraums übernimmt den Segmentseitentyp, während der Kernelraum seine eigenen Regeln hat. Dieser Artikel zielt darauf ab, die Adresszuordnung des Kernelraums zu untersuchen.
  • OS weist jedem Prozess einen unabhängigen, kontinuierlichen virtuellen Adressspeicherplatz zu. Die Größe beträgt im Allgemeinen 4G (32-Bit-Betriebssystem, also 2 hoch 32), wobei der Speicherplatz mit hohem Adresswert zugewiesen wird Das Betriebssystem belegt 1 GB, das Betriebssystem des Fensters belegt 2 GB. Der verbleibende Speicheradressraum wird dem Prozess zugewiesen.
  • Normalerweise ist der virtuelle Adressraum des 32-Bit-Linux-Kernels in 0 bis 3 GB als Benutzerbereich und 3 bis 4 GB als Kernelbereich unterteilt (beachten Sie, dass die lineare Adresse, die der Kernel verwenden kann, nur 1 GB beträgt). Beachten Sie, dass dies die Aufteilung des 32-Bit-Kernel-Adressraums ist und die Aufteilung des 64-Bit-Kernel-Adressraums unterschiedlich ist.

  • Prozessadressraum 0 ~ 4G
  • Der Prozess kann im Benutzermodus nur auf 0 ~ 3G zugreifen und nur auf 3G ~ 4G, wenn er in den Kernelmodus wechselt.
  • Der Prozess wechselt durch in den Kernelmodus Systemaufruf
  • Der 3G~4G-Teil des virtuellen Raums jedes Prozesses ist derselbe
  • Der Prozess, der aus dem Benutzermodus in den Kernel-Status wechselt, führt nicht zu Änderungen in CR3, sondern zu Änderungen im Stapel

2. High-End-Speicher des Linux-Kernels

1. Ursprung

Wenn der Kernelmodulcode oder -thread auf den Speicher zugreift, sind die Speicheradressen im Code alle logische Adressen und entsprechen der tatsächlichen physischen Speicheradresse, eine Eins-zu-Eins-Zuordnung B. ist die physische Adresse, die der logischen Adresse 0xc0000003 entspricht, 0 × 3, die physische Adresse, die 0xc0000004 entspricht, ist 0 × 4, ..., die Beziehung zwischen der logischen Adresse und der physischen Adresse ist Physische Adresse = logische Adresse – 0xC0000000: Dies ist die Adressübersetzungsbeziehung des Kernel-Adressraums. Achten Sie auf die virtuelle Adresse des Kernels. Die virtuelle Adresse befindet sich am „oberen Ende“, die von ihr abgebildete physische Speicheradresse jedoch am unteren Ende .

Logische AdressePhysische Speicheradresse0xc00000000xc00000010xc0000002 0xc0000003…0xe0000000…0xffffffff0×40000000 ??

Unter der Annahme, dass gemäß der obigen einfachen Adresszuordnungsbeziehung der Zugriff auf den logischen Kernel-Adressraum 0xc0000000 ~ 0xffffffff beträgt, beträgt der entsprechende physische Speicherbereich 0 × 0 ~ 0 × 40000000, dh es kann nur auf 1 GB physischen Speicher zugegriffen werden. Wenn 8 GB physischer Speicher in der Maschine installiert sind, kann der Kernel nur auf die ersten 1 GB physischen Speicher zugreifen, und auf die folgenden 7 GB physischen Speicher kann nicht zugegriffen werden, da der Adressraum des Kernels vollständig dem Adressbereich 0 × des physischen Speichers zugeordnet wurde 0 ~ 0×40000000. Selbst wenn 8G physischer Speicher installiert sind, wie greift der Kernel auf den Speicher mit der physischen Adresse 0×40000001 zu? Der Code muss eine logische Speicheradresse haben. Der Adressraum von 0xc0000000 bis 0xffffffff ist aufgebraucht, sodass auf den Speicher nach der physischen Adresse 0×40000000 nicht zugegriffen werden kann.

Offensichtlich kann der Kernel-Adressraum 0xc0000000 ~ 0xfffffff nicht für die einfache Adresszuordnung verwendet werden. Daher unterteilt die x86-Architektur den Kernel-Adressraum in drei Teile: ZONE_DMA, ZONE_NORMAL und ZONE_HIGHMEM. ZONE_HIGHMEM ist High-End-Speicher, der den Ursprung des Konzepts des High-End-Speichers darstellt.


In der x86-Struktur sind die drei Arten von Zonen (berechnet aus 3G) wie folgt:

ZONE_DMA       16 MB am Anfang des Speichers

ZONE_NORMAL   16 MB ~ 896 MB

ZONE_HIGHMEM 896 MB ~ Ende (1G)

2. Verständnis

Wir haben vorhin den Ursprung des High-End-Speichers erklärt. Linux unterteilt den Kernel-Adressraum in drei Teile: ZONE_DMA, ZONE_NORMAL und ZONE_HIGHMEM. Der High-End-Speicher-HIGH_MEM-Adressraum reicht von 0xF8000000 bis 0xFFFFFFFF (896 MB bis 1024 MB). Wie nutzt der Kernel also den 128 MB großen High-End-Speicheradressraum, um auf den gesamten physischen Speicher zuzugreifen? Wenn der Kernel auf Speicher mit einer physischen Adresse von mehr als 896 MB zugreifen möchte, findet er einen freien logischen Adressraum entsprechender Größe im Adressraumbereich von 0xF8000000 ~ 0xFFFFFFFF und leiht ihn sich für eine Weile aus. Leihen Sie sich diesen logischen Adressraum aus und ordnen Sie ihn dem physischen Speicher zu, auf den Sie zugreifen möchten (dh füllen Sie die PTE-Seitentabelle des Kernels aus. Verwenden Sie ihn vorübergehend für eine Weile und geben Sie ihn nach der Verwendung zurück). Auf diese Weise können andere diesen Adressraum auch ausleihen, um auf andere physische Speicher zuzugreifen, wodurch ein begrenzter Adressraum für den Zugriff auf alle physischen Speicher erreicht wird. Wie unten gezeigt.

Zum Beispiel möchte der Kernel ab 2G auf einen physischen Speicher von 1 MB zugreifen, dh der physische Adressbereich beträgt 0 × 80000000 ~ 0x800FFFFF. Suchen Sie vor dem Zugriff zunächst einen freien Adressraum von 1 MB. Nehmen Sie an, dass der gefundene freie Adressraum 0xF8700000 ~ 0xF87FFFFF ist. Verwenden Sie diesen logischen Adressraum von 1 MB, um ihn dem Speicher im physischen Adressraum 0x80000000 ~ 0x800FFFFF zuzuordnen. Die Zuordnungsbeziehung ist wie folgt:

0×0
0 ×1
0×2
0×3
0×20000000
Logische Adresse 0×800000000×800000010×80000002 …0x800FFFFF
Physische Speicheradresse 0xF8700000
0 xF87000 01
0xF8700002
0xF87FFFFF

Nachdem der Kernel auf den physischen Speicher 0×80000000 ~ 0x800FFFFF zugreift, gibt er den linearen Kernelraum 0xF8700000 ~ 0xF87FFFFF frei. Auf diese Weise können auch andere Prozesse oder Codes die Adresse 0xF8700000 ~ 0xF87FFFFF verwenden, um auf anderen physischen Speicher zuzugreifen.

Aus der obigen Beschreibung können wir die grundlegendste Idee des High-End-Speichers erkennen: Leihen Sie sich einen Abschnitt des Adressraums aus, erstellen Sie eine temporäre Adresszuordnung und geben Sie ihn nach der Verwendung frei. Es kann recycelt werden und auf den gesamten physischen Speicher zugreifen.

Bei diesem Anblick kommen einige Leute nicht umhin, sich zu fragen: Was passiert, wenn ein Kernel-Prozess oder ein Kernel-Modul weiterhin einen bestimmten logischen Adressraum belegt und ihn nicht freigibt? Wenn diese Situation tatsächlich auftritt, wird der High-End-Speicheradressraum des Kernels immer knapper. Wenn er belegt und nicht freigegeben ist, ist er nicht zugänglich, selbst wenn er nicht dem physischen Speicher zugeordnet ist.

3. Aufteilung

Der Kernel unterteilt den High-End-Speicher in 3 Teile: VMALLOC_START~VMALLOC_END, KMAP_BASE~FIXADDR_START und FIXADDR_START~4G.

Für High-End-Speicher können Sie die entsprechende Seite über alloc_page() oder andere Funktionen erhalten. Wenn Sie jedoch auf den tatsächlichen physischen Speicher zugreifen möchten, müssen Sie die Seite in eine lineare Adresse umwandeln (warum? Denken Sie darüber nach, wie die MMU auf den physischen Speicher zugreift. Das heißt, wir müssen einen linearen Platz für die Seite finden, die dem High-End-Speicher entspricht. Dieser Vorgang wird als High-End-Speicherzuordnung bezeichnet.

Entspricht den drei Teilen des High-End-Speichers. Es gibt drei Möglichkeiten der High-End-Speicherzuordnung:


Zuordnung zum „Kernel Dynamic Mapping Space“ (nicht zusammenhängende Speicherzuweisung) Diese Methode ist sehr einfach, da sie über vmalloc erfolgt (), in „Kernel Dynamic Mapping“ Bei der Beantragung von Speicher-„Speicherplatz“ ist es möglich, Seiten aus dem High-End-Speicher abzurufen (siehe Implementierung von vmalloc), sodass es möglich ist, dass High-End-Speicher dem „ Kernel Dynamic Mapping Space“.

Permanente Kernel-Zuordnung Wenn die Seite, die dem High-End-Speicher entspricht, über alloc_page() abgerufen wird, wie findet man dann einen linearen Platz dafür?
Der Kernel stellt hierfür speziell einen linearen Raum zur Verfügung, von PKMAP_BASE bis FIXADDR_START, für die Zuordnung von High-End-Speicher. Auf dem 2.6-Kernel liegt dieser Adressbereich zwischen 4G-8M und 4G-4M. Dieser Raum wird „Kernel Permanent Mapping Space“ oder „Permanent Kernel Mapping Space“ genannt. Dieser Bereich verwendet dieselbe Seitenverzeichnistabelle wie andere Bereiche. Für den Kernel ist es swapper_pg_dir. Bei normalen Prozessen wird darauf durch das CR3-Register verwiesen. Normalerweise ist dieser Speicherplatz 4 MB groß, sodass nur eine Seitentabelle benötigt wird. Der Kernel sucht über pkmap_page_table nach dieser Seitentabelle. Über kmap() kann eine Seite diesem Bereich zugeordnet werden. Da dieser Speicherplatz 4 MB groß ist, können bis zu 1024 Seiten gleichzeitig abgebildet werden. Daher sollten nicht verwendete Seiten rechtzeitig aus diesem Bereich freigegeben werden (dh die Zuordnungsbeziehung wird freigegeben, und die einer Seite entsprechende lineare Adresse kann aus diesem Bereich freigegeben werden).

Temporäre Kernel-Zuordnung Der Kernel reserviert etwas linearen Platz zwischen FIXADDR_START und FIXADDR_TOP für besondere Anforderungen. Dieser Raum wird als „fester Mapping-Raum“ bezeichnet. Ein Teil davon wird für die temporäre Zuordnung von High-End-Speicher verwendet.

Dieser Raum hat die folgenden Eigenschaften:

(1) Jede CPU belegt einen Raum
(2) Der von jeder CPU belegte Raum ist in mehrere kleine Räume unterteilt, jeder kleine Raum ist 1 Seite, jeder kleine Raum wird für einen bestimmten Zweck verwendet , und diese Zwecke sind in km_type in kmap_types.h definiert.

Wenn Sie eine temporäre Zuordnung durchführen möchten, müssen Sie den Zweck der Zuordnung angeben. Entsprechend dem Zuordnungszweck können Sie den entsprechenden kleinen Bereich finden und dann die Adresse dieses Bereichs als Zuordnungsadresse verwenden. Dies bedeutet, dass eine temporäre Zuordnung dazu führt, dass die vorherige Zuordnung überschrieben wird. Die temporäre Zuordnung erfolgt über kmap_atomic().

3. Andere

1. Hat der Benutzerraum (Prozess) das Konzept des High-End-Speichers?

Benutzerprozesse haben kein Konzept für High-End-Speicher. Hoher Speicher existiert nur im Kernel-Bereich. Benutzerprozesse können nur auf bis zu 3 GB physischen Speicher zugreifen, während Kernelprozesse auf den gesamten physischen Speicher zugreifen können.

2. Gibt es High-End-Speicher im 64-Bit-Kernel?

In der aktuellen Realität gibt es im 64-Bit-Linux-Kernel keinen High-End-Speicher, da der 64-Bit-Kernel mehr als 512 GB Speicher unterstützen kann. Wenn der auf dem Computer installierte physische Speicher den Kernel-Adressraum überschreitet, steht High-End-Speicher zur Verfügung.

3. Auf wie viel physischen Speicher kann ein Benutzer zugreifen? Auf wie viel physischen Speicher kann der Kernel-Code zugreifen?

32-Bit-Systembenutzerprozesse können auf bis zu 3 GB zugreifen, und Kernelcode kann auf den gesamten physischen Speicher zugreifen.

64-Bit-Systembenutzerprozesse können auf maximal mehr als 512 GB zugreifen, und Kernelcode kann auf den gesamten physischen Speicher zugreifen.

4. Welche Beziehung besteht zwischen High-End-Speicher und physischer Adresse, logischer Adresse und linearer Adresse?

High-End-Speicher bezieht sich nur auf logische Adressen und hat keine direkte Beziehung zu logischen Adressen und physischen Adressen.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Linux-Benutzerraums und des Kernelraums. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen