


Erfahren Sie in einem Artikel mehr über die Speicherzuweisungsstrategie von Linux
Wie sieht die Speicherverteilung eines Linux-Prozesses aus?
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:
- Der Kernel-Speicherplatz eines 32-Bit-Systems belegt 1 GB, also ganz oben, und die restlichen 3 GB sind Benutzerspeicherplatz
- Der Kernelraum und der Benutzerraum von 64-Bit-Systemen sind beide 128T groß und belegen den höchsten bzw. niedrigsten Teil des gesamten Speicherraums, und der verbleibende mittlere Teil ist undefiniert.
Lassen Sie uns über den Unterschied zwischen Kernel-Space und User-Space sprechen:
- Wenn sich der Prozess im Benutzermodus befindet, kann er nur auf den Benutzerspeicher zugreifen
- Erst nach Eingabe des Kernel-Status können Sie auf den Speicher im Kernel-Bereich zugreifen
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:

- Programmdateisegment, einschließlich binärem ausführbarem Code
- Initialisiertes Datensegment, einschließlich statischer Konstanten
- Nicht initialisierte Datensegmente, einschließlich nicht initialisierter statischer Variablen
- Heap-Segmente, einschließlich dynamisch zugewiesenem Speicher, beginnen bei niedrigen Adressen und wachsen nach oben
- Dateizuordnungssegmente, einschließlich dynamischer Bibliotheken, gemeinsam genutzter Speicher usw., beginnen bei niedrigen Adressen und wachsen nach oben (abhängig von der Hardware- und Kernel-Version);
- Stapelsegment, einschließlich lokaler Variablen und Funktionsaufrufkontext usw. Die Stapelgröße ist fest und beträgt normalerweise 8 MB. Natürlich stellt das System auch Parameter bereit, damit wir die Größe anpassen können
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.
Wie reserviert malloc Speicher?
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.
- Methode 1: Reservieren Sie Speicher vom Heap über den Systemaufruf brk()
- Methode 2: Weisen Sie Speicher im Dateizuordnungsbereich über den Systemaufruf mmap() zu Die Implementierung der ersten Methode ist sehr einfach. Sie besteht darin, die Funktion brk() zu verwenden, um den Zeiger „Top of Heap“ auf eine hohe Adresse zu verschieben, um neuen Speicherplatz zu erhalten. Wie unten gezeigt:


“
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:
- Wenn der vom Benutzer zugewiesene Speicher weniger als 128 KB beträgt, beantragen Sie Speicher über brk(); Wenn der vom Benutzer zugewiesene Speicher größer als 128 KB ist, beantragen Sie Speicher über mmap();
- Beachten Sie, dass verschiedene Glibc-Versionen unterschiedliche Schwellenwerte definieren. malloc() reserviert physischen Speicher?
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? Wennmalloc() Speicher zuweist, wird der Speicherplatz nicht entsprechend der vom Benutzer erwarteten Anzahl von Bytes zugewiesen, sondern wird vorab einen größeren Speicherplatz als Speicherpool zugewiesen.
Die 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.

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:
- Der von malloc über brk() angewendete Speicher gibt den Speicher nicht an das Betriebssystem zurück, sondern wird für die nächste Verwendung im Speicherpool von malloc zwischengespeichert Wenn free den von malloc zugewiesenen Speicher über
- mmap() freigibt, gibt den Speicher an das Betriebssystem zurück und der Speicher wird tatsächlich freigegeben.
Warum verwenden nicht alle mmap, um Speicher zuzuweisen?
Da die Beantragung von Speicher vom Betriebssystem einen Systemaufruf erfordert, müssen Sie in den Kernel-Status wechseln und dann in den Benutzerstatus zurückkehren.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.
Da brk so großartig ist, warum nicht brk für alle Zuweisungen verwenden?
Wir haben bereits erwähnt, dass der über brk vom Heap-Speicher zugewiesene Speicher nicht an das Betriebssystem zurückgegeben wird. Betrachten wir also ein solches Szenario.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 .

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.
Die Funktion free() übergibt nur eine Speicheradresse. Warum kann sie wissen, wie viel Speicher freigegeben werden muss?
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!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

VS Code system requirements: Operating system: Windows 10 and above, macOS 10.12 and above, Linux distribution processor: minimum 1.6 GHz, recommended 2.0 GHz and above memory: minimum 512 MB, recommended 4 GB and above storage space: minimum 250 MB, recommended 1 GB and above other requirements: stable network connection, Xorg/Wayland (Linux)

Die Gründe für die Installation von VS -Code -Erweiterungen können sein: Netzwerkinstabilität, unzureichende Berechtigungen, Systemkompatibilitätsprobleme, VS -Code -Version ist zu alt, Antiviren -Software oder Firewall -Interferenz. Durch Überprüfen von Netzwerkverbindungen, Berechtigungen, Protokolldateien, Aktualisierungen von VS -Code, Deaktivieren von Sicherheitssoftware und Neustart von Code oder Computern können Sie Probleme schrittweise beheben und beheben.

Obwohl Notepad den Java -Code nicht direkt ausführen kann, kann er durch Verwendung anderer Tools erreicht werden: Verwenden des Befehlszeilencompilers (JAVAC), um eine Bytecode -Datei (Dateiname.class) zu generieren. Verwenden Sie den Java Interpreter (Java), um Bytecode zu interpretieren, den Code auszuführen und das Ergebnis auszugeben.

VS Code ist der vollständige Name Visual Studio Code, der eine kostenlose und open-Source-plattformübergreifende Code-Editor und Entwicklungsumgebung von Microsoft ist. Es unterstützt eine breite Palette von Programmiersprachen und bietet Syntax -Hervorhebung, automatische Codebettel, Code -Snippets und intelligente Eingabeaufforderungen zur Verbesserung der Entwicklungseffizienz. Durch ein reiches Erweiterungs -Ökosystem können Benutzer bestimmte Bedürfnisse und Sprachen wie Debugger, Code -Formatierungs -Tools und Git -Integrationen erweitern. VS -Code enthält auch einen intuitiven Debugger, mit dem Fehler in Ihrem Code schnell gefunden und behoben werden können.

VS -Code ist auf Mac verfügbar. Es verfügt über leistungsstarke Erweiterungen, GIT -Integration, Terminal und Debugger und bietet auch eine Fülle von Setup -Optionen. Für besonders große Projekte oder hoch berufliche Entwicklung kann VS -Code jedoch Leistung oder funktionale Einschränkungen aufweisen.

Visual Studio Code (VSCODE) ist ein plattformübergreifender, Open-Source-Editor und kostenloser Code-Editor, der von Microsoft entwickelt wurde. Es ist bekannt für seine leichte, Skalierbarkeit und Unterstützung für eine Vielzahl von Programmiersprachen. Um VSCODE zu installieren, besuchen Sie bitte die offizielle Website, um das Installateur herunterzuladen und auszuführen. Bei der Verwendung von VSCODE können Sie neue Projekte erstellen, Code bearbeiten, Code bearbeiten, Projekte navigieren, VSCODE erweitern und Einstellungen verwalten. VSCODE ist für Windows, MacOS und Linux verfügbar, unterstützt mehrere Programmiersprachen und bietet verschiedene Erweiterungen über den Marktplatz. Zu den Vorteilen zählen leicht, Skalierbarkeit, umfangreiche Sprachunterstützung, umfangreiche Funktionen und Versionen

Zu den Hauptanwendungen von Linux gehören: 1. Server -Betriebssystem, 2. Eingebettes System, 3. Desktop -Betriebssystem, 4. Entwicklungs- und Testumgebung. Linux zeichnet sich in diesen Bereichen aus und bietet Stabilität, Sicherheits- und effiziente Entwicklungstools.

Um die Git -Repository -Adresse anzuzeigen, führen Sie die folgenden Schritte aus: 1. Öffnen Sie die Befehlszeile und navigieren Sie zum Repository -Verzeichnis; 2. Führen Sie den Befehl "git remote -v" aus; 3.. Zeigen Sie den Repository -Namen in der Ausgabe und der entsprechenden Adresse an.
