Heim  >  Artikel  >  Betrieb und Instandhaltung  >  In welchem ​​Bereich läuft der Linux-Treiber?

In welchem ​​Bereich läuft der Linux-Treiber?

青灯夜游
青灯夜游Original
2022-11-10 20:02:391950Durchsuche

Linux-Treiber laufen im „Kernel“-Bereich. Im Allgemeinen rufen Treiber kmalloc() auf, um Speicher für Datenstrukturen zuzuweisen, rufen vmalloc() auf, um Datenstrukturen für aktive Auslagerungsbereiche zuzuweisen, Puffer für einige E/A-Treiber zuzuweisen oder kmalloc und vmalloc zuzuweisen, um Kernelspeicher zuzuweisen.

In welchem ​​Bereich läuft der Linux-Treiber?

Die Betriebsumgebung dieses Tutorials: Linux7.3-System, Dell G3-Computer.

Linux-Treiber laufen im „Kernel“-Bereich.

Bei allgemein geschriebenen Mikrocontroller-Programmen sind Anwendungen und Treiber häufig gemischt. Mikrocontroller-Programmierer mit einem bestimmten Maß an Fähigkeiten können die Schichtung von Anwendungen und Treibern realisieren. In Linux-Systemen wurde eine Schichtung von Anwendungen und Treibern erzwungen.

Im Mikrocontroller-Programm kann die Anwendung die zugrunde liegenden Register direkt bedienen. Ein solches Verhalten ist jedoch in Linux-Systemen verboten. Beispielsweise ruft der Autor einer Linux-Anwendung absichtlich den Energieverwaltungstreiber in der Anwendung auf und fährt das System herunter.

Die spezifische Linux-Anwendung ruft den Treiber auf, wie in der Abbildung gezeigt:

In welchem ​​Bereich läuft der Linux-Treiber?

Die Anwendung wird im Benutzerbereich ausgeführt und der Treiber wird im Kernelbereich ausgeführt. Wenn eine Anwendung im Benutzerbereich den Kernel bedienen möchte, muss sie eine „Systemaufruf“-Methode durchlaufen, um vom Benutzerbereich aus in den Kernelbereich zu gelangen und die unterste Ebene zu bedienen.

Kernelraum unter Linux

Der Kernel ist ebenfalls ein Programm und sollte auch über einen eigenen virtuellen Speicherraum verfügen. Als Programm, das Benutzerprogramme bedient, hat der Kernelraum jedoch seine eigenen Eigenschaften.

Die Beziehung zwischen Kernel-Speicherplatz und Benutzerspeicherplatz

In einem 32-Bit-System kann der virtuelle Speicherplatz eines Programms bis zu 4 GB betragen. Der direkteste Weg besteht daher darin, den Kernel als zu erstellendes Programm zu betrachten es verfügt wie andere Programme auch über 4 GB Speicherplatz. Dieser Ansatz führt jedoch dazu, dass das System ständig zwischen der Seitentabelle des Benutzerprogramms und der Kernel-Seitentabelle wechselt, was sich negativ auf die Effizienz des Computers auswirkt. Der beste Weg, dieses Problem zu lösen, besteht darin, den 4-GB-Speicherplatz in zwei Teile zu unterteilen: einen Teil ist Benutzerraum und der andere Teil ist Kernel-Speicherplatz. Dadurch kann sichergestellt werden, dass der Kernel-Speicherplatz fest und unverändert bleibt und beim Programmwechsel nur der Programmänderungen. Der einzige Nachteil dieses Ansatzes besteht darin, dass sowohl der Kernel- als auch der Benutzerraum kleiner werden.

Zum Beispiel: Auf einer 32-Bit-Hardwareplattform wie i386 definiert Linux eine Konstante PAGE_OFFSET in der Datei page.h:

#ifdef CONFIG_MMU
#define __PAGE_OFFSET  (0xC0000000)        //0xC0000000为3GB
#else
#define __PAGE_OFFSET  (0x00000000)
#endif

#define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)

Linux verwendet PAGE_OFFSET als Grenze, um den virtuellen 4-GB-Speicherplatz in zwei Teile zu unterteilen: Adresse Der niedrige Adressraum von 0 bis 3G-1 ist der Benutzerraum mit einer Größe von 3 GB; der hohe Adressraum von 3 GB bis 4 GB-1 ist der Kernelraum mit einer Größe von 1 GB.

Wenn mehrere Programme im System ausgeführt werden, kann die Beziehung zwischen mehreren Benutzerräumen und dem Kernelraum wie folgt ausgedrückt werden:

In welchem ​​Bereich läuft der Linux-Treiber?

Wie in der Abbildung gezeigt, teilen sich die Programme 1, 2 ... n den Kernelraum . Mit „Teilen“ ist hier natürlich „Time-Sharing“ gemeint, da auf einem Single-Core-Prozessorsystem zu jedem Zeitpunkt nur ein Programm ausgeführt werden kann.

Das Gesamtlayout des Kernelraums

Im Entwicklungsprozess von Linux ist die Entwicklung des Kernelraumlayouts mit der Aktualisierung der Hardwareausrüstung und der Verbesserung des technischen Niveaus auch eine Möglichkeit des kontinuierlichen Patchens. Dies hat zur Folge, dass der Kernelraum in mehrere unterschiedliche Bereiche unterteilt ist und unterschiedliche Bereiche unterschiedliche Zuordnungsmethoden haben.

Normalerweise wird angenommen, dass der Linux-Kernelraum drei Bereiche hat, nämlich den DMA-Bereich (ZONE_DMA), den normalen Bereich (ZONE_NORMAL) und den High-End-Speicherbereich (ZONE_HIGHMEM).

Direkte Zuordnung des Kernel-Speicherplatzes, wenn der tatsächliche physische Speicher klein ist

Der in frühen Computern konfigurierte tatsächliche physische Speicher beträgt normalerweise nur wenige MB, also

Um die Geschwindigkeit des Kernels beim Zugriff auf physische Adressen zu verbessern Speicher durch virtuelle Adressen, Virtualisierung des Kernelraums Die Adresse und die physische Speicheradresse übernehmen eine feste Zuordnungsmethode, die eins zu eins von der niedrigen Adresse zur hohen Adresse entspricht:

In welchem ​​Bereich läuft der Linux-Treiber?Wie Sie können Sehen Sie,

Diese feste Zuordnungsmethode sorgt dafür, dass die virtuelle Adresse und die physische Speicheradresse einander entsprechen. Die Beziehung zwischen den Adressen wird sehr einfach, das heißt, die virtuelle Kerneladresse und die tatsächliche physische Adresse unterscheiden sich nur um a Fester Offset PAGE_OFFSET. Wenn der Kernel also die virtuelle Adresse verwendet, um auf den physischen Seitenrahmen zuzugreifen, muss er nur PAGE_OFFSET von der virtuellen Adresse subtrahieren. Sie können die tatsächliche physische Adresse erhalten, was viel schneller ist als die Verwendung der Seitentabelle!

Da diese Methode physische Adressen fast direkt verwendet, wird dieser auf fester Zuordnung basierende Kernelraum auch als „physischer Speicherplatz“ oder kurz physischer Speicher bezeichnet. Darüber hinaus Da es sich bei der festen Mapping-Methode um eine lineare Mapping-Methode handelt, wird dieser Bereich auch als linearer Mapping-Bereich bezeichnet.

In diesem Fall (wenn der tatsächliche physische Speicher des Computers klein ist) nimmt der feste Kernel-Mapping-Speicherplatz natürlich nur einen Teil des gesamten 1-GB-Kernel-Speicherplatzes ein. Beispiel: Bei der Konfiguration eines x86-Computersystems mit 32 MB tatsächlichem physischem Speicher ist der feste Zuordnungsbereich des Kernels der 32 MB große Speicherplatz von PAGE_OFFSET ~ (PAGE_OFFSET + 0x02000000). Was tun also mit dem verbleibenden virtuellen Kernelraum im Kernelraum?

Natürlich wird der physische Speicher weiterhin bei der nichtlinearen Zuordnung von Seitentabellen gemäß der normalen Methode zur Verwaltung des virtuellen Speicherplatzes verwendet. Konkret wird der feste Zuordnungsbereich aus dem gesamten 1-GB-Kernelraum entfernt, und dann wird zu Beginn ein 8-MB-Isolationsbereich aus dem verbleibenden Teil entfernt. Der Rest ist ein gewöhnlicher virtueller Speicherzuordnungsbereich, der auf die gleiche Weise wie der Benutzerraum zugeordnet wird . In diesem Bereich gibt es nicht nur keine feste Zuordnungsbeziehung zwischen virtuellen Adressen und physischen Adressen, sondern durch Aufrufen der Kernelfunktion vmalloc () wird auch dynamischer Speicher abgerufen. Daher wird dieser Bereich als vmalloc-Zuordnungsbereich bezeichnet, wie in der folgenden Abbildung dargestellt :

In welchem ​​Bereich läuft der Linux-Treiber?

Für ein x86-Computersystem, das mit 32 MB tatsächlichem physischem Speicher konfiguriert ist, ist die Startposition des vmalloc-Zuweisungsbereichs PAGE_OFFSET+0x02000000+0x00800000.

Lassen Sie es mich hier erklären:

Die hier erwähnte feste Zuordnung zwischen Kernelraum und physischen Seitenrahmen ist im Wesentlichen eine „Reservierung“ von Kernelseiten zu physischen Seitenrahmen. Dies bedeutet nicht, dass diese Seiten diese physischen Seitenrahmen „belegen“. Das heißt, die virtuelle Seite ist nur dann an den physischen Seitenrahmen gebunden, wenn die virtuelle Seite tatsächlich auf den physischen Seitenrahmen zugreifen muss. Wenn ein physischer Seitenrahmen nicht von der entsprechenden virtuellen Seite verwendet wird, kann der Seitenrahmen normalerweise vom Benutzerbereich und dem später eingeführten Kernel-kmalloc-Zuweisungsbereich verwendet werden.

Kurz gesagt, in einem System mit einem kleinen tatsächlichen physischen Speicher ist die tatsächliche Speichergröße die Grenze zwischen dem physischen Speicherbereich des Kernelraums und dem vmalloc-Zuweisungsbereich.

ZONE_DMA-Bereich und ZONE_NORMAL-Bereich

Für den gesamten 1-GB-Kernelraum werden die 16 MB an der Spitze des Raums auch als DMA-Bereich bezeichnet, also als ZONE_DMA-Bereich, da in der Vergangenheit die Hardware verwendet wurde Der DMA-Speicherplatz im physischen Speicher wurde korrigiert. Die verbleibenden 16 MB werden als normale Bereiche bezeichnet, nämlich ZONE_NORMAL.

High-End-Speicher des Kernelraums

Mit der Entwicklung der Computertechnologie wird der tatsächliche physische Speicher des Computers immer größer, wodurch der feste Zuordnungsbereich des Kernels (linearer Bereich) größer wird und größer. Wenn keine Einschränkungen auferlegt werden, wird der vmalloc-Zuweisungsbereich (nichtlinearer Bereich) natürlich nicht mehr existieren, wenn der tatsächliche physische Speicher 1 GB erreicht. Daher ist der zuvor entwickelte Kernel-Code, der vmalloc() aufrief, nicht mehr verfügbar, um mit dem frühen Kernel-Code kompatibel zu sein.

Die folgende Abbildung zeigt die Situation dieses Kernelraums:

In welchem ​​Bereich läuft der Linux-Treiber?

Offensichtlich

Der Grund für das obige Problem liegt darin, dass nicht erwartet wurde, dass der tatsächliche physische Speicher 1 GB überschreiten kann, sodass die Grenze des Kernels festgelegt wurde Der Zuordnungsbereich wurde nicht festgelegt und lässt ihn wachsen, wenn der tatsächliche physische Speicher zunimmt.

Der Weg, das obige Problem zu lösen, ist:

Begrenzen Sie die Obergrenze des festen Zuordnungsbereichs des Kernelraums, sodass er mit zunehmendem physischen Speicher nicht beliebig vergrößert werden kann. Linux legt fest, dass der obere Grenzwert des Kernel-Mapping-Bereichs nicht größer als ein konstanter High_menory-Wert sein darf, der kleiner als 1G ist. Wenn der tatsächliche physische Speicher groß ist, wird 3G+high_memory als Grenze zur Bestimmung des physischen Speicherbereichs verwendet.

Zum Beispiel: Bei x86-Systemen beträgt der Wert von high_memory 896 MB, sodass die verbleibenden 128 MB von 1 GB Kernelspeicher ein nichtlinearer Zuordnungsbereich sind. Dadurch wird sichergestellt, dass der Kernel in jedem Fall über genügend nichtlinearen Mapping-Bereich verfügt, um mit frühem Code kompatibel zu sein, und auf normale Weise auf mehr als 1 GB tatsächlichen physischen Speicher zugreifen kann.

Mit anderen Worten, die grundlegendste Idee von High-End-Speicher: Einen Abschnitt des Adressraums ausleihen, eine temporäre Adresszuordnung erstellen und ihn nach der Verwendung freigeben. Dieser Adressraum kann recycelt werden, um auf den gesamten physischen Speicher zuzugreifen. Wenn der Computer über einen großen physischen Speicher verfügt, sieht das schematische Diagramm des Kernelraums wie folgt aus:

In welchem ​​Bereich läuft der Linux-Treiber?

Traditionell nennt Linux diesen Teil des Kernelraums 3G+high_memory~4G-1 den High-End-Speicherbereich ( ZONE_HIGHMEM).

Zusammenfassend: Im Kernelraum der x86-Struktur lauten die drei Arten von Bereichen (berechnet aus 3G) wie folgt:

  • ZONE_DMA: Kernel-Speicherplatz beginnend mit 16 MB Je nach Anwendungsziel unterschiedlich, High-End Der Speicher ist in vmalloc-Bereich, persistenten Mapping-Bereich und temporären Mapping-Bereich unterteilt.
  • Das Layout des High-End-Speichers im Kernelraum ist in der folgenden Abbildung dargestellt:
  • vmalloc-Zuordnungsbereich

Der vmalloc-Zuordnungsbereich ist der Hauptteil des High-End-Speichers Lücke zwischen dem Kopf dieses Intervalls und dem linearen Mapping-Bereich des Kernels. Ein 8-MB-Isolationsbereich und ein 4-KB-Isolationsbereich am Ende und ein anschließender persistenter Mapping-Bereich.

Die Zuordnungsmethode des vmalloc-Zuordnungsbereichs ist genau die gleiche wie die des Benutzerbereichs. Der Kernel kann Speicher in diesem Bereich abrufen, indem er die Funktion vmalloc () aufruft. Die Funktion dieser Funktion entspricht malloc() im Benutzerbereich. Der bereitgestellte Speicherplatz ist kontinuierlich an der virtuellen Adresse (beachten Sie, dass die physische Adresse nicht garantiert kontinuierlich ist). In welchem ​​Bereich läuft der Linux-Treiber?

Persistenter Kernel-Zuordnungsbereich

Wenn die Seite, die dem High-End-Speicher entspricht, über alloc_page () abgerufen wird, wie findet man dann einen linearen Raum dafür?

Der Kernel stellt zu diesem Zweck speziell einen linearen Raum bereit, beginnend mit PKMAP_BASE, der zum Zuordnen des High-End-Speichers verwendet wird, bei dem es sich um den persistenten Kernel-Zuordnungsbereich handelt.

Im persistenten Kernel-Mapping-Bereich können Sie durch Aufrufen der Funktion kmap() eine langfristige Zuordnung zwischen dem physischen Seitenrahmen und der virtuellen Kernel-Seite herstellen. Dieser Speicherplatz beträgt normalerweise 4 MB und kann bis zu 1024 Seitenrahmen abbilden. Um den Umschlag von Seitenrahmen zu erhöhen, sollte daher die Funktion kunmap() rechtzeitig aufgerufen werden, um die vorhandenen physischen Seitenrahmen freizugeben nicht mehr verwendet.

Temporärer Mapping-Bereich

Der temporäre Mapping-Bereich wird auch als fester Mapping-Bereich und reservierter Bereich bezeichnet. Dieser Bereich wird hauptsächlich in Multiprozessorsystemen verwendet. Da der in diesem Bereich erhaltene Speicherplatz nicht geschützt ist, muss der erhaltene Speicher rechtzeitig verwendet werden. Andernfalls wird der Inhalt des Seitenrahmens überschrieben . , daher wird dieser Bereich als temporärer Zuordnungsbereich bezeichnet.

Ein sehr guter Artikel über den High-End-Speicherbereich: Linux User Space und Kernel Space – detaillierte Erklärung des High-End-Speichers.

Kernel-Speicherzuweisungsmodifikator gfp

Um die notwendigen Erklärungen für Anforderungen in der Kernel-Speicheranforderungsfunktion bereitzustellen, definiert Linux eine Vielzahl von Speicherzuweisungsmodifikatoren gfp. Es handelt sich um Verhaltensmodifikatoren, Flächenmodifikatoren und Typmodifikatoren.

Verhaltensmodifikatoren Verhaltensmodifikatoren in Speicherzuweisungsfunktionen beschreiben, wie der Kernel Speicher zuweisen soll. Die wichtigsten Verhaltensmodifikatoren sind wie folgt:

Hauptverhaltensmodifikatoren für die Kernel-Speicherzuordnung

Modifikator Beschreibung

__GFP_WAITRegionsmodifikator Linux-Hauptkernel-Speicherzuweisungsbereichsmodifikator Modifikator Beschreibung
Allocator kann schlafen.
__GFP_HIGH Allocator Kann auf den Notfall-Ereignispuffer zugreifen pool
__GFP_IO Der Allokator kann Festplatten-IO starten.
__GFP_FS Der Allokator kann Dateisystem-IO starten aus dem Cache
__GFP_NOWARN Allocator gibt keine Warnungen aus
__GFP_REPEAT Reallocate bei Zuordnungsfehler
__GFP_NOFAILT Reallocate bei Zuordnungsfehler bis zum Erfolg
__GFP_NORETRY Nicht mehr, wenn die Zuweisung fehlschlägt. Neuzuweisung
Der Regionsmodifikator gibt an, aus welcher Region des Kernel-Speicherplatzes Speicher zugewiesen werden muss. Standardmäßig beginnt der Speicherzuweiser bei ZONE_NORMAL im Kernelraum und weist dem Speicheranforderer nach und nach Speicherbereiche zu. Wenn der Benutzer speziell Speicher von ZONE_DMA oder ZONE_HOGNMEM abrufen muss, muss der Speicheranforderer die folgenden beiden Bereiche im Speicher verwenden Anforderungsfunktion. Modifikatorbeschreibung:

__GFP_DMASpeicher aus dem ZONE_DMA-Bereich zuweisen

__ GFP_HIGHMEM Speicher aus der Zone ZONE_HIGHMEM zuweisen

类型修饰符

类型修饰符实质上是上述所述修饰符的联合应用。也就是:将上述的某些行为修饰符和区修饰符,用“|”进行连接并另外取名的修饰符。这里就不多介绍了。

内核常用内存分配及地址映射函数

函数vmalloc()

函数vmalloc()在vmalloc分配区分配内存,可获得虚拟地址连续,但并不保证其物理页框连续的较大内存。与物理空间的内存分配函数malloc()有所区别,vmalloc()分配的物理页不会被交换出去。函数vmalloc()的原型如下:

void *vmalloc(unsigned long size)
{
       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
}
void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
{
	return kmalloc(size, (gfp_mask | __GFP_COMP) & ~__GFP_HIGHMEM);
}

其中,参数size为所请求内存的大小,返回值为所获得内存虚拟地址指针。

与vmalloc()配套的释放函数如下:

void vfree(const void *addr)
{
	kfree(addr);
}

其中,参数addr为待释放内存指针。

函数kmalloc()

kmalloc()是内核另一个常用的内核分配函数,它可以分配一段未清零的连续物理内存页,返回值为直接映射地址。由kmalloc()可分配的内存最大不能超过32页。其优点是分配速度快,缺点是不能分配大于128KB的内存页(出于跨平台考虑)。

在linux/slab.h文件中,该函数的原型声明如下:

static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
	struct kmem_cache *cachep;
	void *ret;

	if (__builtin_constant_p(size)) {
		int i = 0;

		if (!size)
			return ZERO_SIZE_PTR;

#define CACHE(x) \
		if (size <= x) \
			goto found; \
		else \
			i++;
#include <linux/kmalloc_sizes.h>
#undef CACHE
		return NULL;
found:
#ifdef CONFIG_ZONE_DMA
		if (flags & GFP_DMA)
			cachep = malloc_sizes[i].cs_dmacachep;
		else
#endif
			cachep = malloc_sizes[i].cs_cachep;

		ret = kmem_cache_alloc_notrace(cachep, flags);

		trace_kmalloc(_THIS_IP_, ret,
			      size, slab_buffer_size(cachep), flags);

		return ret;
	}
	return __kmalloc(size, flags);
}

其中,参数size为以字节为单位表示的所申请空间的大小;参数flags决定了所分配的内存适合什么场合。

与函数kmalloc()对应的释放函数如下:

void kfree(const void *objp)
{
	struct kmem_cache *c;
	unsigned long flags;

	trace_kfree(_RET_IP_, objp);

	if (unlikely(ZERO_OR_NULL_PTR(objp)))
		return;
	local_irq_save(flags);
	kfree_debugcheck(objp);
	c = virt_to_cache(objp);
	debug_check_no_locks_freed(objp, obj_size(c));
	debug_check_no_obj_freed(objp, obj_size(c));
	__cache_free(c, (void *)objp);
	local_irq_restore(flags);
}

小结一下,kmalloc、vmalloc、malloc的区别:

  • kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存;
  • kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西;
  • kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大;
  • vmalloc比kmalloc要慢。

也就是说:kmalloc、vmalloc这两个函数所分配的内存都处于内核空间,即从3GB~4GB;但位置不同,kmalloc()分配的内存处于3GB~high_memory(ZONE_DMA、ZONE_NORMAL)之间,而vmalloc()分配的内存在VMALLOC_START~4GB(ZONE_HIGHMEM)之间,也就是非连续内存区。一般情况下在驱动程序中都是调用kmalloc()来给数据结构分配内存,而vmalloc()用在为活动的交换区分配数据结构,为某些I/O驱动程序分配缓冲区,或为模块分配空间。

In welchem ​​Bereich läuft der Linux-Treiber?

可参考文章:Kmalloc和Vmalloc的区别

函数alloc_pages()

与上述在虚拟空间分配内存的函数不同,alloc_pages()是在物理内存空间分配物理页框的函数,其原型如下:

static inline struct page * alloc_pages(gfp_t gfp_mask, unsigned int order)
{
	if (unlikely(order >= MAX_ORDER))
		return NULL;

	return alloc_pages_current(gfp_mask, order);
}

其中,参数order表示所分配页框的数目,该数目为2^order。order的最大值由include/Linux/Mmzone.h文件中的宏MAX_ORDER决定。参数gfp_mask为说明内存页框分配方式及使用场合。

函数返回值为页框块的第一个页框page结构的地址。

调用下列函数可以获得页框的虚拟地址:

void *page_address(struct page *page)
{
	unsigned long flags;
	void *ret;
	struct page_address_slot *pas;
 
	if (!PageHighMem(page))
		return lowmem_page_address(page);
 
	pas = page_slot(page);
	ret = NULL;
	spin_lock_irqsave(&pas->lock, flags);
	if (!list_empty(&pas->lh)) {
		struct page_address_map *pam;
 
		list_for_each_entry(pam, &pas->lh, list) {
			if (pam->page == page) {
				ret = pam->virtual;
				goto done;
			}
		}
	}
done:
	spin_unlock_irqrestore(&pas->lock, flags);
	return ret;
}

使用函数alloc_pages()获得的内存应该使用下面的函数释放:

void __free_pages(struct page *page, unsigned int order)
{
	if (put_page_testzero(page)) {
		if (order == 0)
			free_hot_page(page);
		else
			__free_pages_ok(page, order);
	}
}

函数kmap()

kmap()是一个映射函数,它可以将一个物理页框映射到内核空间的可持久映射区。这种映射类似于内核ZONE_NORMAL的固定映射,但虚拟地址与物理地址的偏移不一定是PAGE_OFFSET。由于内核可持久映射区的容量有限(总共只有4MB),因此当内存使用完毕后,应该立即释放。

函数kmap()的函数原型如下:

void *kmap(struct page *page)
{
	might_sleep();
	if (!PageHighMem(page))
		return page_address(page);
	return kmap_high(page);
}

小结

由于CPU的地址总线只有32位, 32的地址总线无论是从逻辑上还是从物理上都只能描述4G的地址空间(232=4Gbit),在物理上理论上最多拥有4G内存(除了IO地址空间,实际内存容量小于4G),逻辑空间也只能描述4G的线性地址空间。

为了合理的利用逻辑4G空间,Linux采用了3:1的策略,即内核占用1G的线性地址空间,用户占用3G的线性地址空间。所以用户进程的地址范围从0~3G,内核地址范围从3G~4G,也就是说,内核空间只有1G的逻辑线性地址空间。

Wenn der physische Linux-Speicher weniger als 1 GB Speicherplatz umfasst, ordnet der Kernel den physischen Speicher normalerweise linear seinem Adressraum zu, dh einer Eins-zu-Eins-Zuordnung, was die Zugriffsgeschwindigkeit verbessern kann. Wenn der physische Speicher von Linux jedoch 1 GB überschreitet, reicht der lineare Zugriffsmechanismus nicht aus, da nur 1 GB Speicher zugeordnet werden kann und der verbleibende physische Speicher nicht vom Kernel verwaltet werden kann. Um dieses Problem zu lösen, muss Linux die Adresse angeben ist in zwei Teile unterteilt: linearer Bereich und nichtlinearer Bereich. Der lineare Bereich ist auf maximal 896 MB festgelegt, und die restlichen 128 MB sind der nichtlineare Bereich. Daher wird der durch den linearen Bereich abgebildete physische Speicher zum Low-End-Speicher und der verbleibende physische Speicher wird als High-End-Speicher bezeichnet. Im Gegensatz zu linearen Regionen werden nichtlineare Regionen nicht vorab im Speicher zugeordnet, sondern bei Verwendung dynamisch zugeordnet.

Low-End-Speicher ist in zwei Teile unterteilt: ZONE_DMA: 16 MB am Anfang des Kernelraums, ZONE_NORMAL: 16 MB ~ 896 MB des Kernelraums (feste Zuordnung). Der Rest ist High-End-Speicher: ZONE_HIGHMEM: Kernel-Speicherplatz 896 MB ~ Ende (1 GB).

Je nach unterschiedlichen Anwendungszielen ist der High-End-Speicher in drei Teile unterteilt: vmalloc-Bereich, persistenter Zuordnungsbereich und temporärer Zuordnungsbereich. Der vmalloc-Bereich wird mit der Funktion vmalloc() zugewiesen. Der persistente Zuordnungsbereich verwendet allc_pages(), um die entsprechende Seite abzurufen, und der temporäre Zuordnungsbereich wird im Allgemeinen für spezielle Anforderungen verwendet. „Benutzerraum und Kernelraum“

Ja Persistenter Mapping-Bereich
vmalloc-BereichSeitenverzeichnis –> Zwischenseitenverzeichnis “

Low-End-Speicher (3G~3G+high_memory-1)

Linearer Mapping-Bereich (fester Mapping-Bereich)

ZONE_NORMAL
ZONE_DMA
Benutzerbereich (0~3G-1)

Verwandte Empfehlungen: „

Linux-Video-Tutorial

Das obige ist der detaillierte Inhalt vonIn welchem ​​Bereich läuft der Linux-Treiber?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn