Hai bisogno di informazioni sulla traccia malloc

1

Quando provo il codice qui sotto non sono chiaramente in grado di analizzare le chiamate interne di malloc api. Quello che non sono chiaro riguarda la chiamata di sistema mmap è chiamata solo una volta per 2 o più chiamate malloc.Se sto assegnando più di 4069 anche i byte chiamano internamente solo un mmap (la traccia viene identificata usando strace -p processid).

#include<stdio.h>
#include<stdlib.h>

main()
{
int *p,*q;
sleep(20);
p=malloc(5096);
printf("p=%p\n",p);
q=malloc(4096);
printf("q=%p\n",q);
sleep(2);
return 0;
}

strace OUTPUT:

root@TEST:/home/harish# strace  -p 6109
Process 6109 attached
restart_syscall(<... resuming interrupted call ...>
) = 0
brk(0)                                  = 0xeca000
brk(0xeec000)                           = 0xeec000
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 14), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f10b7bc7000
write(1, "p=0xeca010\n", 11)            = 11
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({20, 0},
0x7ffc34a51790)      = 0
write(1, "q=0xecb020\n", 11)            = 11
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({2, 0}, 0x7ffc34a51790)       = 0
exit_group(0)                           = ?
+++ exited with 0 +++

Quello che sto cercando è che se si usa malloc più di una volta chiamerà più di un mmap poiché la memoria sta superando in due malloc oltre 4096

    
posta torban 17.06.2016 - 06:25
fonte

1 risposta

3

Se vuoi veramente capire% interni di% co_de, guarda nel codice sorgente. Sui sistemi Linux è probabile che sia in GNU libc ma ci sono altre implementazioni della libreria standard C (la musl-libc codice sorgente è piacevole da leggere) e di malloc (ad esempio tcmalloc ). Qui è un malloc molto veloce e semplice, ma completamente inutile dato che fallisce sempre.

Grossolanamente, malloc è sempre costruito sopra i sistema operativo primitivi (cioè chiamate di sistema , per Linux elencato in syscalls (2) ) che modifica lo spazio di indirizzi virtuali . Concretamente ciò significa principalmente mmap (2) & malloc (e forse anche l'obsoleto sbrk (2) , ecc ... ) su Linux.

Il sistema operativo kernel sta gestendo lo spazio degli indirizzi virtuali di pagine (spesso 4Kbytes su x86) utilizzando la MMU . Quindi la dimensione della pagina è definita dall'hardware.

L'implementazione di munmap(2) & malloc può essere difficile. Innanzitutto, ovviamente non free un'intera pagina di 4Kbyte per ogni piccolo mmap (ad esempio 24 o 32 byte), poiché ciò sprecherebbe spazio. Quindi chiamerebbe malloc una volta ogni tanto e organizza saggiamente le pagine ottenute. Quindi, probabilmente mmap un grande segmento (di molte pagine consecutive) per grandi allocazioni (ad esempio un po 'di mmap di due megabyte). Cerca anche di riutilizzare in precedenza malloc -d zone di memoria, perché chiamare free è molto più lento di una normale chiamata di funzione.

Quindi la maggior parte di mmap -s gestisce almeno piccole zone e larghezze diverse, e alcuni malloc -s sono ancora più intelligenti. Per esempio, la lib gestiva un elenco collegato di piccole zone della stessa dimensione e, per ottenere lo spazio iniziale, potrebbe malloc una o più pagine consecutive. Quindi, mmap -ing zone così piccole sta aggiungendo la zona free -d a quella lista collegata. Quindi la maggior parte piccola free -s non utilizzerà malloc ma semplicemente ottiene un elemento per tali elenchi. Per le zone di grandi dimensioni l'implementazione potrebbe mmap e mmap ciascuna di esse. Alcune implementazioni di munmap mantengono le dimensioni della zona in una parola poco prima della zona.

Nei dettagli, l'implementazione sta facendo cose molto più difficili (ad esempio, non utilizzare elenchi, ma tentativi , usa diverse regioni o arene, potresti allocare piccoli mallocs di due parole in intervalli di indirizzi specifici, ecc ...). Puoi trovare molti documenti di ricerca su malloc (perché ci sono molti compromessi da considerare) e diversi tutorial, ad es. questo . Leggi anche la frammentazione & garbage collection (a volte usando GC Boehm conservativo è utile nei programmi in C: utilizzerai malloc anziché GC_MALLOC e non ti preoccuperai di chiamare malloc ), ad esempio leggi il manuale GC .

GNU libc fornisce mallinfo (3) , malloc_info(3) , mallopt(3) , mcheck (3) ecc. Il programma valgrind è molto utile per cacciare perdite di memoria e corruzioni.

BTW, potresti usare strace (1) (e forse anche ltrace (1) ...) direttamente:

strace ./yourprog

PS. La mia risposta è focalizzata su Linux. Su altri sistemi operativi i dettagli sono diversi.

    
risposta data 17.06.2016 - 06:40
fonte

Leggi altre domande sui tag