Im Linux-Betriebssystem ist das Innere des virtuellen Adressraums in zwei Teile unterteilt: Kernelraum und Benutzerraum Systeme mit unterschiedlichen Ziffern haben unterschiedliche Adressraumbereiche. Die gängigsten 32-Bit- und 64-Bit-Systeme sind beispielsweise die folgenden:
Sie können es hier sehen:
Lassen Sie uns über den Unterschied zwischen Kernel-Space und User-Space sprechen:
Obwohl jeder Prozess seinen eigenen unabhängigen virtuellen Speicher hat, Die Kerneladresse in jedem virtuellen Speicher ist tatsächlich demselben physischen Speicher zugeordnet. Auf diese Weise kann der Prozess nach dem Wechsel in den Kernel-Status problemlos auf den Kernel-Speicher zugreifen.
Als nächstes erfahren wir mehr über die Aufteilung des virtuellen Raums und des Kernelraums. Über die Verteilung des Kernelraums werde ich nicht viel sagen.
Werfen wir einen Blick auf die Verteilung des Benutzerraums. Am Beispiel eines 32-Bit-Systems habe ich ein Bild gezeichnet, um ihre Beziehung zu zeigen:
Auf diesem Bild können Sie sehen, dass der Benutzerspeicher in 6 verschiedene Speichersegmente von niedrig bis hoch unterteilt ist:
Unter diesen 6 Speichersegmenten wird der Speicher der Heap- und Dateizuordnungssegmente dynamisch zugewiesen. Mit malloc() oder mmap() der C-Standardbibliothek können Sie beispielsweise Speicher im Heap- bzw. Dateizuordnungssegment dynamisch zuweisen.
Tatsächlich ist malloc() kein Systemaufruf, sondern eine Funktion in der C-Bibliothek, die zum dynamischen Zuweisen von Speicher verwendet wird.
Wenn malloc Speicher beantragt, gibt es zwei Möglichkeiten, Heap-Speicher vom Betriebssystem zu beantragen.
“
Unter welchen Umständen reserviert malloc() Speicher über brk()? In welchem Szenario wird Speicher über mmap() zugewiesen?
“
malloc() hat einen standardmäßig im Quellcode definierten Schwellenwert:
Nein,
malloc() reserviert virtuellen Speicher.
Wenn auf den zugewiesenen virtuellen Speicher nicht zugegriffen wird, wird der virtuelle Speicher nicht dem physischen Speicher zugeordnet, sodass er keinen physischen Speicher belegt. Nur beim Zugriff auf den zugewiesenen virtuellen Adressraum durchsucht das Betriebssystem die Seitentabelle und stellt fest, dass sich die dem virtuellen Speicher entsprechende Seite nicht im physischen Speicher befindet. Es löst einen Seitenfehler-Interrupt aus und erstellt dann einen Verbindung zwischen dem virtuellen Speicher und der physischen Speicherzuordnungsbeziehung zwischen.
Wie viel virtuellen Speicher wird malloc(1) zuweisen? WennDie spezifische Menge an Speicherplatz, die vorab zugewiesen wird, hängt vom von malloc verwendeten Speichermanager ab. Zur Analyse verwenden wir den Standardspeichermanager von malloc (Ptmalloc2). Als nächstes führen wir ein Experiment durch und verwenden den folgenden Code, um zu sehen, wie viel Speicherplatz tatsächlich vom Betriebssystem zugewiesen wird, wenn über malloc 1 Byte Speicher beantragt wird.
#include #include int main() { printf("使用cat /proc/%d/maps查看内存分配\n",getpid()); //申请1字节的内存 void *addr = malloc(1); printf("此1字节的内存起始地址:%x\n", addr); printf("使用cat /proc/%d/maps查看内存分配\n",getpid()); //将程序阻塞,当输入任意字符时才往下执行 getchar(); //释放内存 free(addr); printf("释放了1字节的内存,但heap堆并不会释放\n"); getchar(); return 0; }
Führen Sie den Code aus (
Lassen Sie mich im Voraus erklären, die Version der Glibc-Bibliothek, die ich verwende, ist 2.17):
Wir können die Speicherverteilung des Prozesses über die Datei /proc//maps anzeigen. Ich filtere den Bereich der Speicheradressen in der Maps-Datei anhand dieser 1-Byte-Speicherstartadresse heraus.
[root@xiaolin ~]# cat /proc/3191/maps | grep d730 00d73000-00d94000 rw-p 00000000 00:00 0 [heap]
Sie können sehen, dass der Speicheradressbereich des Heap-Speichers 00d73000-00d94000 beträgt und die Größe dieses Bereichs 132 KB beträgt, was bedeutet, dass
malloc(1) tatsächlich 132 KB Speicher vorab zuweist.
Einige Schüler haben vielleicht bemerkt, dass die Startadresse des im Programm gedruckten Speichers d73010 ist, während die Kartendatei zeigt, dass die Startadresse des Heap-Speicherplatzes d73000 ist. Warum gibt es eine zusätzliche 0x10 (16 Bytes)? Lassen wir diese Frage zunächst beiseite und sprechen später darüber. #free Wird freigegebener Speicher an das Betriebssystem zurückgegeben?
Führen wir den obigen Prozess aus, um zu sehen, ob der Heap-Speicher noch vorhanden ist, nachdem der Speicher über die Funktion free() freigegeben wurde.
Wie Sie auf dem Bild unten sehen können, ist der Heap-Speicher nach dem Freigeben des Speichers noch vorhanden und wurde nicht an das Betriebssystem zurückgegeben.Das liegt daran, dass es besser ist, dieses 1 Byte an das Betriebssystem weiterzugeben, es zwischenzuspeichern und in den Speicherpool von malloc zu legen. Wenn der Prozess erneut 1 Byte Speicher beansprucht, kann es direkt wiederverwendet werden ist viel schneller.
Wenn der Prozess beendet wird, beansprucht das Betriebssystem natürlich alle Ressourcen des Prozesses zurück.
Der Heap-Speicher ist weiterhin vorhanden, nachdem der oben erwähnte freie Speicher für den von malloc über brk() angewendeten Speicher gilt.
Wenn malloc über mmap Speicher anfordert, wird dieser an das Betriebssystem zurückgegeben, nachdem der Speicher freigegeben wurde.
Lassen Sie uns ein Experiment durchführen, um zu überprüfen, ob wir 128 KB Speicher über malloc beantragen, sodass malloc Speicher über mmap zuweist.
#include #include int main() { //申请1字节的内存 void *addr = malloc(128*1024); printf("此128KB字节的内存起始地址:%x\n", addr); printf("使用cat /proc/%d/maps查看内存分配\n",getpid()); //将程序阻塞,当输入任意字符时才往下执行 getchar(); //释放内存 free(addr); printf("释放了128KB字节的内存,内存也归还给了操作系统\n"); getchar(); return 0; }
Ausführungscode:
Wenn Sie sich die Speicherverteilung des Prozesses ansehen, können Sie feststellen, dass ganz rechts keine [Kopf]-Markierung vorhanden ist, was darauf hinweist, dass der anonyme Speicher aus dem Dateizuordnungsbereich über mmap durch anonyme Zuordnung zugewiesen wird.
Dann lasst uns diese Erinnerung freigeben und sehen:
Überprüfen Sie erneut die Startadresse des 128-KB-Speichers. Sie können feststellen, dass dieser nicht mehr vorhanden ist, was darauf hinweist, dass er an das Betriebssystem zurückgegeben wurde.
Zur Frage „Wird der von malloc beantragte und von free freigegebene Speicher an das Betriebssystem zurückgegeben?“ können wir zusammenfassen:
Daher sollten bei der Beantragung von Speicher häufige Systemaufrufe vermieden werden. Wenn mmap zum Zuweisen von Speicher verwendet wird, bedeutet dies, dass jedes Mal Systemaufrufe ausgeführt werden müssen.
Da außerdem der von mmap zugewiesene Speicher bei jeder Freigabe an das Betriebssystem zurückgegeben wird, befindet sich die von mmap zugewiesene virtuelle Adresse jedes Mal in einem Seitenfehlerzustand, und zwar auch dann, wenn zum ersten Mal auf die virtuelle Adresse zugegriffen wird Zu diesem Zeitpunkt wird ein Seitenfehler-Interrupt ausgelöst.
Mit anderen Worten:
Wenn Speicher häufig über mmap zugewiesen wird, wird nicht nur jedes Mal der Betriebsstatus geändert, sondern es kommt auch zu einem Seitenfehler-Interrupt (nach dem ersten Zugriff auf die virtuelle Adresse), der zu einem hohen CPU-Verbrauch führt .
Um diese beiden Probleme zu verbessern, weist malloc beim Freigeben des Speichers direkt größeren Speicher als Speicherpool zu, wenn er über den Systemaufruf brk () Speicher im Heap-Speicherplatz beantragt , Im Speicherpool zwischengespeichert.
Wenn Sie das nächste Mal Speicher beantragen, entnehmen Sie einfach den entsprechenden Speicherblock direkt aus dem Speicherpool. Die Zuordnungsbeziehung zwischen der virtuellen Adresse und der physischen Adresse dieses Speicherblocks besteht möglicherweise weiterhin. Dadurch wird nicht nur die Anzahl reduziert Systemaufrufe, Es reduziert auch die Anzahl der Seitenfehler-Interrupts, was den CPU-Verbrauch erheblich reduziert.
Wenn wir nacheinander drei Speicherstücke mit 10 KB, 20 KB und 30 KB beantragen, wenn 10 KB und 20 KB freigegeben werden und zu freiem Speicherplatz werden, und wenn der für das nächste Mal beantragte Speicher weniger als 30 KB beträgt, kann dieser freie Speicherplatz wiederverwendet werden .
Aber wenn der beim nächsten Mal angeforderte Speicher größer als 30 KB ist, ist kein freier Speicherplatz verfügbar und Sie müssen einen Antrag auf das Betriebssystem stellen, und der tatsächlich verwendete Speicher erhöht sich weiter.
Da das System häufig Mallocs und Freigaben durchführt, insbesondere bei kleinen Speicherblöcken, werden immer mehr unbrauchbare Fragmente im Heap generiert, was zu „Speicherlecks“ führt. Dieses „Leckage“-Phänomen kann mit Valgrind nicht erkannt werden.
Daher werden bei der Implementierung von malloc die Unterschiede, Vor- und Nachteile im Verhalten von brk und mmap vollständig berücksichtigt und standardmäßig ein großer Speicherblock (128 KB) zugewiesen, bevor mmap zum Zuweisen von Speicherplatz verwendet wird.
Erinnern Sie sich, ich habe bereits erwähnt, dass die Startadresse des von malloc an den Benutzermodus zurückgegebenen Speichers 16 Byte größer ist als die Startadresse des Heap-Speicherplatzes des Prozesses?
In den zusätzlichen 16 Bytes werden die Beschreibungsinformationen des Speicherblocks gespeichert, beispielsweise die Größe des Speicherblocks.
Auf diese Weise versetzt free beim Ausführen der Funktion free () die eingehende Speicheradresse um 16 Bytes nach links und analysiert dann die Größe des aktuellen Speicherblocks aus diesen 16 Bytes und weiß natürlich, wie groß er ist Der Speicher muss freigegeben werden.
Das obige ist der detaillierte Inhalt vonErfahren Sie in einem Artikel mehr über die Speicherzuweisungsstrategie von Linux. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!