Heim  >  Artikel  >  Betrieb und Instandhaltung  >  Detaillierte Erläuterung der virtuellen Speicherverwaltung

Detaillierte Erläuterung der virtuellen Speicherverwaltung

PHP中文网
PHP中文网Original
2017-06-20 11:23:263542Durchsuche

Moderne Betriebssysteme verwenden im Allgemeinen einen Mechanismus zur virtuellen Speicherverwaltung (Virtual Memory Management), der Unterstützung durch die MMU (Memory Management Unit) im Prozessor erfordert. Zunächst werden die Konzepte PA und VA vorgestellt.

1.PA (Physical Address) ---Physical Address

Wenn der Prozessor keine MMU hat oder eine MMU vorhanden ist, diese aber nicht aktiviert ist, wird die vom Prozessor ausgegebene Speicheradresse angezeigt Die CPU-Ausführungseinheit wird direkt an den Chip-Engine-Pin übertragen und vom Speicherchip (im Folgenden als physischer Speicher bezeichnet, um ihn vom virtuellen Speicher zu unterscheiden) empfangen, der als PA (Physical Address, im Folgenden als PA bezeichnet) bezeichnet wird. , wie in der Abbildung unten gezeigt.

Detaillierte Erläuterung der virtuellen Speicherverwaltung

Physische Adresse

2.VA (Virtuelle Adresse) ---Virtuelle Adresse

Wenn der Prozessor MMU aktiviert hat, ist die CPU führt aus Die von der Einheit gesendete Speicheradresse wird von der MMU abgefangen. Die Adresse von der CPU an die MMU wird als virtuelle Adresse (im Folgenden als VA bezeichnet) bezeichnet, und die MMU übersetzt diese Adresse in eine andere Adresse und sendet sie an die Externer Adress-Pin des CPU-Chips. Das heißt, VA wird PA zugeordnet, wie in der Abbildung unten gezeigt.

Detaillierte Erläuterung der virtuellen Speicherverwaltung

Virtuelle Adresse

Wenn es sich um einen 32-Bit-Prozessor handelt, ist der interne Adressbus 32-Bit und mit der CPU-Ausführungseinheit verbunden (in der Abbildung sind nur 4 Adressleitungen schematisch dargestellt), während dies beim externen Adressbus nach der MMU-Konvertierung nicht der Fall ist Es muss 32-Bit sein. Mit anderen Worten: virtueller Adressraum und physischer Adressraum sind unabhängig Der virtuelle Adressraum eines 32-Bit-Prozessors beträgt 4 GB, während der physische Adressraum größer oder kleiner als 4 GB sein kann.

Die MMU ordnet VA in Seiteneinheiten (Seite) zu. Die Seitengröße von 32-Bit-Prozessoren beträgt normalerweise 4 KB. Beispielsweise kann die MMU über ein Zuordnungselement eine Seite von 0xb7001000~0xb7001fff in VA einer Seite von 0x2000~0x2fff in PA zuordnen. Wenn die CPU-Ausführungseinheit auf die virtuelle Adresse 0xb7001008 zugreifen möchte, ist die tatsächliche physische Adresse, auf die zugegriffen wird, 0x2008. Seiten im physischen Speicher werden als physische Seiten oder Seitenrahmen bezeichnet. Welche Seite des virtuellen Speichers welchem ​​Seitenrahmen des physischen Speichers zugeordnet ist, wird durch die Seitentabelle (Seitentabelle) beschrieben. Die Seitentabelle wird im physischen Speicher gespeichert, um zu bestimmen, welche PA eine VA haben soll abgebildet werden.

3. Adressraum verarbeiten

Detaillierte Erläuterung der virtuellen SpeicherverwaltungAdressraum verarbeiten

Der virtuelle Adressraum der x86-Plattform ist 0x0000 0000~0xffff ffff. Im Allgemeinen sind die ersten 3 GB (0x0000 0000~0xbfff ffff) Benutzerraum und die letzten 1 GB (0xc000 0000~0xffff ffff) sind Kernelraum.

Textsegment und Datensegment

  • Textsegment, einschließlich .text-Segment, .rodata-Segment, .plt-Segment usw. Es wird von /bin/bash in den Speicher geladen und die Zugriffsberechtigung ist r-x.

  • Datensegment, einschließlich .data-Segment, .bss-Segment usw. Es wird auch von /bin/bash in den Speicher geladen und die Zugriffsberechtigung ist rw-.

Heap und Stack

  • Heap : Der Heap ist einfach der verbleibende Speicherplatz im Computerspeicher, malloc Die Funktion reserviert hier dynamisch Speicher. Bei der dynamischen Zuweisung von Speicher kann der Heap-Speicherplatz zu höheren Adressen hin wachsen. Die Obergrenze der Adresse des Heap-Speichers wird als Break bezeichnet. Um den Heap-Speicherplatz auf eine hohe Adresse zu vergrößern, muss der Break angehoben werden, um neue virtuelle Speicherseiten dem physischen Speicher zuzuordnen. Dies wird durch den Systemaufruf brk erreicht Die Funktion ruft auch brk auf, um die Zuweisung vom Kernelspeicher anzufordern.

  • Stapel : Der Stapel ist ein spezifischer Speicherbereich, in dem der Teil mit hoher Adresse die Umgebungsvariablen und Befehlszeilenparameter des Prozesses speichert, und der Teil mit niedriger Adresse Der Teil -address speichert die Umgebungsvariablen und Befehlszeilenparameter des Prozesses teilweise. Der Stack-Speicherplatz wächst in Richtung niedrigerer Adressen, aber es gibt offensichtlich nicht so viel Platz für Wachstum wie den Heap-Speicherplatz, da dies nicht ungewöhnlich ist Tatsächliche Anwendungen müssen dynamisch große Mengen an Speicher zuweisen, aber es gibt Dutzende Schichten in der Tiefe. Es kommt sehr selten vor, dass Funktionsaufrufe auf jeder Ebene des Aufrufs viele lokale Variablen haben.

Wenn Sie beim Schreiben eines Programms nicht auf die Speicherzuordnung achten, können folgende Probleme im Heap und Stack auftreten:

  1. Speicherverlust: Wenn Sie über malloc in einer Funktion einen Platz im Heap beantragen und eine Zeigervariable auf dem Stapel deklarieren, um ihn zu speichern, werden beim Ende der Funktion die Mitgliedsvariablen der Funktion freigegeben , einschließlich dieser Zeigervariablen, kann dieser Speicherplatz nicht gefunden und nicht freigegeben werden. Im Laufe der Zeit kann es zu den folgenden Speicherverlustproblemen kommen.

  2. Stapelüberlauf: Wenn Sie zu viele Daten auf den Stapel legen (z. B. große Strukturen und Arrays), kann es zu einem „Stapelüberlauf“ (Stapelüberlauf) kommen. Frage, das Programm wird auch beendet. Um dieses Problem zu vermeiden, sollte malloc verwendet werden, um beim Deklarieren solcher Variablen Heap-Speicherplatz zu beantragen.

  3. Wilder Zeiger und Segmentierungsfehler: Wenn der durch einen Zeiger angezeigte Speicherplatz freigegeben wurde, versuchen Sie dann, den Zeiger für den Zugriff zu verwenden Der bereits freigegebene Speicherplatz führt zu „Segmentfehler“-Problemen. Zu diesem Zeitpunkt ist der Zeiger zu einem Wild-Zeiger geworden, und der Wild-Zeiger sollte rechtzeitig manuell gelöscht werden.

4. Die Rolle der virtuellen Speicherverwaltung

  1. Die virtuelle Speicherverwaltung kann Zugriffsrechte auf den physischen Speicher steuern. Der physische Speicher selbst schränkt den Zugriff nicht ein und jede Adresse kann gelesen und geschrieben werden. Das Betriebssystem erfordert jedoch unterschiedliche Zugriffsrechte. Dies wird durch die Verwendung des Speicherschutzmechanismus des CPU-Modus und der MMU erreicht.

  2. Die Hauptfunktion der virtuellen Speicherverwaltung besteht darin, jedem Prozess einen unabhängigen Adressraum zu ermöglichen. Der sogenannte unabhängige Adressraum bedeutet, dass dieselbe VA in verschiedenen Prozessen durch MMU verschiedenen PAs zugeordnet wird und der Zugriff auf eine beliebige Adresse in einem bestimmten Prozess nicht auf die Daten eines anderen Prozesses zugreifen kann Dies stellt sicher dass ein illegaler Speicherzugriff, der durch die Ausführung falscher Anweisungen oder bösartigen Codes durch einen Prozess verursacht wird, nicht versehentlich die Daten anderer Prozesse neu schreibt und den Betrieb anderer Prozesse nicht beeinträchtigt, wodurch die Stabilität des gesamten Systems gewährleistet wird. Andererseits glaubt jeder Prozess, dass er ausschließlich den gesamten virtuellen Adressraum besitzt, sodass es einfacher ist, den Linker und Loader zu implementieren, ohne berücksichtigen zu müssen, ob die Adressbereiche der einzelnen Prozesse in Konflikt stehen.

Detaillierte Erläuterung der virtuellen Speicherverwaltung是独立的

Prozessadressräume sind unabhängig

  1. VA-zu-PA-Zuordnung reserviert und gibt Speicher frei. Das bringt Komfort, Mehrere Speicherblöcke mit diskontinuierlichen physischen Adressen können einem Speicherblock mit kontinuierlichen virtuellen Adressen zugeordnet werden. Wenn Sie beispielsweise malloc verwenden möchten, um einen großen Speicherplatz zuzuweisen, obwohl genügend freier physischer Speicher vorhanden ist, ist nicht genügend kontinuierlicher freier Speicher vorhanden. In diesem Fall können Sie mehrere diskontinuierliche physische Seiten zuweisen und diese einer kontinuierlichen virtuellen Seite zuordnen Adressbereich.

Detaillierte Erläuterung der virtuellen Speicherverwaltung

Diskontinuierliche PA kann auf kontinuierliche VA abgebildet werden

  1. Wenn ein System viele Prozesse gleichzeitig ausführt, kann die Summe des jedem Prozess zugewiesenen Speichers größer sein als der tatsächlich verfügbare physische Speicher, sodass jeder Prozess weiterhin normal ausgeführt werden kann in diesem Fall. Da jedem Prozess nur virtuelle Speicherseiten zugewiesen werden, können die Daten dieser Seiten physischen Seiten zugeordnet oder vorübergehend auf der Festplatte gespeichert werden, ohne die physischen Seiten zu belegen. Die temporäre Speicherung virtueller Speicherseiten auf der Festplatte kann eine Festplatte sein Partition, oder es kann eine Festplattendatei sein, die als Swap-Gerät bezeichnet wird. Wenn der physische Speicher nicht ausreicht, werden die Daten auf einigen selten verwendeten physischen Seiten vorübergehend auf dem Swap-Gerät gespeichert. Dann gilt die physische Seite als frei und kann dem Prozess neu zugewiesen werden aus. Wenn der Prozess die ausgelagerte Seite verwenden möchte, lädt er sie vom Auslagerungsgerät zurück in den physischen Speicher. Dies wird als Einlagern (Einlagern) bezeichnet. Das Auslagern und Einlagern von Vorgängen wird zusammenfassend als Paging bezeichnet, also:

    Die Gesamtmenge an Speicher, die im System zugewiesen werden kann=Größe des physischen Speichers+Größe des Swap-Geräts

Wie im Bild unten gezeigt. Das erste Bild ist das Auslagern, das Speichern der Daten auf der physischen Seite auf der Festplatte, das Aufheben der Zuordnung der Adresse und das Freigeben der physischen Seite. Das zweite Bild besteht aus dem Einlagern, dem Zuweisen einer freien physischen Seite, dem Zurückladen der temporären Seite der Festplatte in den Speicher und dem Einrichten einer Adresszuordnung.

Detaillierte Erläuterung der virtuellen Speicherverwaltung

Seitenwechsel

5.malloc und kostenlos

Die C-Standardbibliotheksfunktion malloc kann dynamisch Speicher im zugrunde liegenden Heap-Speicher zuweisen Beantragen Sie Speicher vom Betriebssystem über den brk-Systemaufruf. Nachdem der dynamisch zugewiesene Speicher aufgebraucht ist, kann er mit free freigegeben, genauer gesagt, an malloc zurückgegeben werden, sodass der Speicher beim nächsten Malloc-Aufruf erneut zugewiesen werden kann.

1 #include <stdlib.h>2 void *malloc(size_t size);  //返回值:成功返回所分配内存空间的首地址,出错返回NULL3 void free(void *ptr);</stdlib.h>
 

malloc的参数size表示要分配的字节数,如果分配失败(可能是由于系统内存耗尽)则返回NULL。由于malloc函数不知道用户拿到这块内存要存放什么类型的数据,所以返回通用指针void *,用户程序可以转换成其它类型的指针再访问这块内存。malloc函数保证它返回的指针所指向的地址满足系统的对齐要求,例如在32位平台上返回的指针一定对齐到4字节边界,以保证用户程序把它转换成任何类型的指针都能用。

动态分配的内存用完之后可以用free释放掉,传给free的参数正是先前malloc返回的内存块首地址。

示例

举例如下:

 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 typedef struct { 5     int number; 6     char *msg; 7 } unit_t; 8 int main(void) 9 {10     unit_t *p = malloc(sizeof(unit_t));11     if (p == NULL) {12         printf("out of memory\n");13         exit(1);14     }15     p->number = 3;16     p->msg = malloc(20);17     strcpy(p->msg, "Hello world!");18     printf("number: %d\nmsg: %s\n", p->number, p->msg);19     free(p->msg);20     free(p);21     p = NULL;22     return 0;23 }</string.h></stdlib.h></stdio.h>

 

说明

  • unit_t *p = malloc(sizeof(unit_t));这一句,等号右边是void *类型,等号左边是unit_t *类型,编译器会做隐式类型转换,我们讲过void *类型和任何指针类型之间可以相互隐式转换。

  • 虽然内存耗尽是很不常见的错误,但写程序要规范,malloc之后应该判断是否成功。以后要学习的大部分系统函数都有成功的返回值和失败的返回值,每次调用系统函数都应该判断是否成功。

  • free(p);之后,p所指的内存空间是归还了,但是p的值并没有变,因为从free的函数接口来看根本就没法改变p的值,p现在指向的内存空间已经不属于用户,换句话说,p成了野指针,为避免出现野指针,我们应该在free(p);之后手动置p = NULL;

  • 应该先free(p->msg),再free(p)。如果先free(p),p成了野指针,就不能再通过p->msg访问内存了。

6.内存泄漏

  如果一个程序长年累月运行(例如网络服务器程序),并且在循环或递归中调用malloc分配内存,则必须有free与之配对,分配一次就要释放一次,否则每次循环都分配内存,分配完了又不释放,就会慢慢耗尽系统内存,这种错误称为内存泄漏(Memory Leak)。另外,malloc返回的指针一定要保存好,只有把它传给free才能释放这块内存,如果这个指针丢失了,就没有办法free这块内存了,也会造成内存泄漏。例如:

1 void foo(void)2 {3     char *p = malloc(10);4     ...5 }

Wenn die Funktion foo zurückkehrt, muss sie den Speicherplatz der lokalen Variablen p freigeben. Die Speicheradresse, auf die sie zeigt, geht verloren und diese 10 Bytes können nicht freigegeben werden. Speicherleckfehler sind schwer zu finden, da sie keine Fehler bei der Programmausführung verursachen, wie z. B. beim Zugriff außerhalb der Grenzen. Eine kleine Menge an Speicherlecks hat keinen Einfluss auf den ordnungsgemäßen Betrieb des Programms. Eine große Anzahl von Speicherlecks führt zu einem Mangel an Systemspeicher, was zu häufigen Seitenwechseln führt, die sich nicht nur auf den aktuellen Prozess auswirken, sondern auch das gesamte System verlangsamen.

Es gibt einige Sonderfälle in Bezug auf Malloc und Free. Der Aufruf von malloc(0) ist ebenfalls zulässig und gibt einen Zeiger ungleich NULL zurück. Dieser Zeiger kann auch zur Freigabe an free übergeben werden, über diesen Zeiger kann jedoch nicht auf den Speicher zugegriffen werden. free(NULL) ist ebenfalls zulässig und bewirkt nichts, aber das Freigeben eines Platzhalterzeigers ist illegal. Wenn Sie beispielsweise zuerst malloc aufrufen, um einen Zeiger p zurückzugeben, und dann zweimal hintereinander aufrufen, wird dies der Fall sein generiert einen Laufzeitfehler.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der virtuellen Speicherverwaltung. 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
Vorheriger Artikel:Verwendung des Befehls chattrNächster Artikel:Verwendung des Befehls chattr