mmap
(bei Verwendung mit MAP_ANONYMOUS
) weist einen Teil des RAM zu, der irgendwo im virtuellen Adressraum des Prozesses platziert werden kann und der später wieder freigegeben werden kann (mit munmap
) unabhängig von allen anderen Zuordnungen.
brk
ändert die Endadresse einer einzelnen, zusammenhängenden "Arena" des virtuellen Adressraums:Wenn diese Adresse erhöht wird, weist sie der Arena mehr Speicher zu, und wenn sie verringert wird, wird der Speicher am Ende der Arena freigegeben. Daher wird Speicher mit brk
zugewiesen kann erst wieder an das Betriebssystem freigegeben werden, wenn ein zusammenhängender Adressbereich am Ende der Arena steht wird vom Prozess nicht mehr benötigt.
Mit brk
für kleine Zuordnungen und mmap
für große Zuweisungen ist eine Heuristik, die auf der Annahme basiert, dass kleine Zuweisungen mit größerer Wahrscheinlichkeit alle dieselbe Lebensdauer haben, während große Zuweisungen eher eine Lebensdauer haben, die nicht mit der Lebensdauer anderer Zuweisungen korreliert. Große Zuweisungen verwenden also das Systemprimitiv, mit dem sie unabhängig von allem anderen freigegeben werden können, und kleine Zuweisungen verwenden das Primitive, das dies nicht tut.
Diese Heuristik ist nicht sehr zuverlässig. Die aktuelle Generation von malloc
Implementierungen hat, wenn ich mich recht erinnere, auf brk
ganz aufgegeben und verwendet mmap
für alles. Die malloc
Ich vermute, dass die Implementierung, die Sie sich ansehen (die in der GNU C-Bibliothek, basierend auf Ihren Tags) sehr alt ist und hauptsächlich weiterhin verwendet wird, weil niemand mutig genug ist, das Risiko einzugehen, sie gegen etwas Neueres auszutauschen, das wahrscheinlich aber nicht sicher besser sein.
Warum also malloc mmap aufruft, wenn es darum geht, eine große Speichergröße zuzuweisen?
Die kurze Antwort lautet für verbesserte Effizienz auf neueren Implementierungen von Linux und den aktualisierten Speicherzuweisungsalgorithmen, die mit ihnen geliefert werden. Denken Sie jedoch daran, dass dies ein sehr implementierungsabhängiges Thema ist und das Warum und Warum für unterschiedliche Jahrgänge und Geschmacksrichtungen des spezifischen Linux-Betriebssystems, das diskutiert wird, stark variieren würde.
Hier ist eine ziemlich neue Beschreibung bezüglich der Low-Level-Teile mmap()
und brk()
Spiel in der Linux-Speicherzuweisung. Und ein nicht so aktueller, aber immer noch relevanter Artikel im Linux Journal, der einige Inhalte enthält, die für das Thema hier sehr aktuell sind, einschließlich dieser:
Bei sehr großen Anfragen verwendet malloc() den Systemaufruf mmap(), um adressierbaren Speicherplatz zu finden. Dieser Prozess trägt dazu bei, die negativen Auswirkungen der Speicherfragmentierung zu reduzieren wenn große Speicherblöcke freigegeben, aber durch kleinere, kürzlich zugewiesene Blöcke gesperrt werden, die zwischen ihnen und dem Ende des zugewiesenen Speicherplatzes liegen. In diesem Fall wäre der Block, wenn er mit brk() zugewiesen worden wäre, für das System unbrauchbar geblieben, selbst wenn der Prozess ihn freigegeben hätte.
(Hervorhebung von mir)
Bezüglich brk()
:
übrigens "...mmap() existierte in den frühen Versionen von Unix nicht. brk()
war damals die einzige Möglichkeit, das Datensegment des Prozesses zu vergrößern. Die erste Unix-Version mit mmap() war Mitte der 80er Jahre SunOS, die erste Open-Source-Version war 1990 BSD-Reno. ". Seit dieser Zeit wurde die moderne Implementierung von Speicherzuweisungsalgorithmen mit vielen Verbesserungen überarbeitet, wodurch die Notwendigkeit für sie, die Verwendung von brk()
einzubeziehen, erheblich reduziert wurde .