2012-08-29 8 views
6

Ich habe über Nacht Speichertests auf einem Embedded-Linux-System ausgeführt. Mit vmstat habe ich beobachtet, dass der freie Speicher im Laufe der Zeit stetig abnimmt. Gemäß einigen smaps Analyse in procfs wächst die Heap eines Prozesses in etwa die gleiche Rate. Ich vermutete ein Speicherleck und fand ein paar Stellen im Code, wo new und delete regelmäßig verwendet werden. Allerdings habe ich keine new Anrufe ohne übereinstimmende delete Anrufe gesehen.Wenn/Wann wird der freigegebene Heap-Speicher freigegeben?

lief ich den Speichertest wieder und heute Morgen die Speicher-Caches mit dem folgenden Aufruf gelöscht

echo 3 > /proc/sys/vm/drop_caches 

Der freie Speicher in vmstat aufgelistet ging auf einen Wert nahe, wenn der Test gestartet wurde.

Gibt der Kernel regelmäßig ungenutzte Heap-Seiten zurück? Wenn ja, gibt es andere Zeiten außer der oben genannten? Wahrscheinlich, wenn der freie Speicher unter eine bestimmte Schwelle sinkt?

+4

Ungenutzter Speicher ist verschwendeter Speicher, also benutzt Linux den Speicher, bis jemand anders ihn benutzen will. – PlasmaHH

+1

sprechen Sie über den Kernel-Heap oder den Heap, der von diesem scheinbar undichten Prozess verwendet wird? –

+0

@Tom: Ich spreche über den Heap des User-Space-Prozesses – waffleman

Antwort

5

Wie andere sagten, ist es die Pflicht des Prozesses, Speicher an den Kernel zurückzugeben.

Normalerweise gibt es 2 Möglichkeiten Speicher zuweisen: Wenn Sie malloc()/new einen Speicherblock über einer bestimmte Größe, die Speicher aus dem O über mmap() zugewiesen bekommen und eturned sobald es frei ist. Kleinere Blöcke werden zugewiesen, indem der Datenbereich des Prozesses erhöht wird, indem die Grenze sbrk nach oben verschoben wird. Dieser Speicher wird nur freigegeben, wenn ein Block über einer bestimmten Größe am Ende dieses Segments frei ist.

z.B .: (Pseudo-Code, ich weiß nicht, C++ sehr gut)

a = new char[1000]; 
b = new char[1000]; 

Speicherkarte:

---------------+---+---+ 
end of program | a | b | 
---------------+---+---+ 

Wenn Sie sich kostenlos a jetzt, Sie haben ein Loch in der Mitte. Es wird nicht freigegeben, da es nicht freigegeben werden kann. Wenn Sie b freigeben, kann der Arbeitsspeicher des Prozesses reduziert werden oder nicht; Der nicht verwendete Rest wird an das System zurückgegeben.

Ein Test mit einem Programm so einfach wie

#include <stdlib.h> 

int main() 
{ 
    char * a = malloc(100000); 
    char * b = malloc(100000); 
    char * c = malloc(100000); 
    free(c); 
    free(b); 
    free(a); 
} 

führt zu einer strace Ausgabe wie

brk(0)         = 0x804b000 
brk(0x8084000)       = 0x8084000 
brk(0x80b5000)       = 0x80b5000 
brk(0x809c000)       = 0x809c000 
brk(0x8084000)       = 0x8084000 
brk(0x806c000)       = 0x806c000 

ist, zeigt, dass der brk Wert zuerst erhöht wird (malloc()) und dann wieder verringert (für free()).

+0

welche Laufzeitbibliothek tut das? –

+0

@TomTanner, glibc erledigt die Speicherverwaltung unter Linux. –

+0

Wird ein Programm jemals tatsächlich seine Größe über 'sbrk' reduzieren? Ich ging immer davon aus, dass die Wahrscheinlichkeit, am Ende einen völlig freien Block zu haben, so gering ist, dass es niemals die Größe reduzieren würde. –

1

Der Kernel wird zwischengespeicherte Speicherseiten zurückfordern, wenn sie benötigt werden, d. H. Wenn das System sonst nicht genügend Arbeitsspeicher hätte. Ob Speicherseiten aus dem Heap der Prozesse (freier Speicher) jemals an das Betriebssystem zurückgegeben werden, liegt im Ermessen des Speichermanagers des Prozesses, in diesem Fall der/Implementierung in der C++ - Bibliothek. Dies ist eine völlig freiwillige Operation, bei der der Kernel nichts zu tun hat.

Aus der Tatsache, dass drop_caches den Trick gemacht hat, können Sie schlussfolgern, dass es der Kernel-Cache war, nicht der Heap des Prozesses, der Speicher auffüllte. Verwenden Sie den Befehl free, um herauszufinden, wie viel Speicher tatsächlich für die Verwendung der Anwendung verfügbar ist, insb. die -/+ buffers/cache Zeile berichtet.

1

Wenn Sie in Ihrem Programm delete aufrufen, kehrt der Speicher zum Speichermanager zurück, der Teil Ihrer Programmlaufzeit ist. Im Prinzip könnte dies geschrieben werden, um den freigegebenen Speicher an das OS zurückzugeben, aber ich würde überrascht sein, wenn dies der Fall wäre. Stattdessen wird der recycelte Speicher für nachfolgende Aufrufe an new zur Seite gehalten.

Beachten Sie, dass dies der virtuelle Speicher Ihres Prozesses ist; Wie viel davon sich tatsächlich während der Programmausführung im physischen Speicher befindet, hängt von der Gesamtsystembelastung ab und wird vom Betriebssystem gehandhabt.

0

Benutzeraufrufe zu malloc und frei (oder neu und löschen), nach meinem besten Wissen nie nicht mehr verwendet Seiten zum O/S zurückgeben. Stattdessen erinnern sie sich nur daran, welcher Speicher freigegeben wurde, so dass, wenn Sie ein malloc/new einer Größe ausführen, die durch zuvor freigegebenen Speicher befriedigt werden kann, diese verwendet, anstatt zum O/S zu gehen und sbrk zu verwenden Mehr Speicherplatz.

So dieser Code:

for (;;) 
{ 
    struct { char data[200 * 1024 * 1024] } HugeBuffer; 
    HugeBuffer *buff = new HugeBuffer; 
    delete buff; 
} 

Wird 200Mb einmal vergeben, und dann, dass der Speicher nur stetig immer verwenden. Es wird einmal auf der ursprünglichen Zuweisung zum O/S gehen und dann im Benutzerraum herumfummeln.

Verwandte Themen