GNU/Linux >> Linux Esercitazione >  >> Linux

Perché malloc() chiama mmap() e brk() in modo intercambiabile?

mmap (se utilizzato con MAP_ANONYMOUS ) alloca un blocco di RAM che può essere posizionato ovunque all'interno dello spazio degli indirizzi virtuali del processo e che può essere deallocato successivamente (con munmap ) indipendentemente da tutte le altre allocazioni.

brk cambia l'indirizzo finale di una singola "arena" contigua dello spazio degli indirizzi virtuali:se questo indirizzo viene aumentato alloca più memoria all'arena, e se viene diminuito, dealloca la memoria alla fine dell'arena. Pertanto, memoria allocata con brk può essere rilasciato al sistema operativo solo quando un intervallo continuo di indirizzi alla fine dell'arena non è più necessario al processo.

Usando brk per piccole allocazioni e mmap per le grandi allocazioni, è un'euristica basata sul presupposto che è più probabile che le piccole allocazioni abbiano tutte la stessa durata, mentre le grandi allocazioni hanno maggiori probabilità di avere una durata che non è correlata con la durata di qualsiasi altra allocazione. Quindi, le allocazioni grandi usano la primitiva di sistema che consente loro di essere deallocate indipendentemente da qualsiasi altra cosa, mentre le allocazioni piccole usano la primitiva che non lo fa.

Questa euristica non è molto affidabile. L'attuale generazione di malloc implements, se non ricordo male, ha rinunciato del tutto a brk e usa mmap per tutto. Il malloc implementazione che sospetto tu stia guardando (quella nella libreria GNU C, basata sui tuoi tag) è molto vecchia e continua principalmente ad essere utilizzata perché nessuno è abbastanza coraggioso da correre il rischio di sostituirla con qualcosa di più nuovo che probabilmente ma non certamente essere migliore.


quindi perché malloc chiama mmap quando si tratta di allocare una grande quantità di memoria?

La risposta breve è per una maggiore efficienza sulle implementazioni più recenti di Linux e sugli algoritmi di allocazione della memoria aggiornati che ne derivano. Ma tieni presente che questo è un argomento molto dipendente dall'implementazione e i perché e i percome varierebbero notevolmente a seconda delle diverse annate e versioni dello specifico sistema operativo Linux in discussione.

Ecco un resoconto abbastanza recente riguardante le parti di basso livello mmap() e brk() gioca nell'allocazione della memoria di Linux. E, un articolo del Linux Journal non così recente, ma ancora rilevante, che include alcuni contenuti che sono molto pertinenti per l'argomento qui, incluso questo:

Per richieste molto grandi, malloc() utilizza la chiamata di sistema mmap() per trovare spazio di memoria indirizzabile. Questo processo aiuta a ridurre gli effetti negativi della frammentazione della memoria quando grandi blocchi di memoria vengono liberati ma bloccati da blocchi più piccoli, allocati più di recente, che si trovano tra loro e la fine dello spazio allocato. In questo caso, infatti, se il blocco fosse stato allocato con brk(), sarebbe rimasto inutilizzabile dal sistema anche se il processo lo avesse liberato.
(sottolineatura mia)

Per quanto riguarda brk() :
incidentalmente, "...mmap() non esisteva nelle prime versioni di Unix. brk() era l'unico modo per aumentare la dimensione del segmento di dati del processo in quel momento. La prima versione di Unix con mmap() fu SunOS a metà degli anni '80, la prima versione open-source fu BSD-Reno nel 1990. ". Da quel momento, l'implementazione moderna degli algoritmi di allocazione della memoria è stata rifattorizzata con molti miglioramenti, riducendo notevolmente la necessità di includerli utilizzando brk() .


Linux
  1. Linux:perché Linux mostra sia più che meno memoria di quella che ho installato fisicamente?

  2. Che cosa significa Env X=() { :;}; Command' Bash Do e perché non è sicuro?

  3. Perché `esce &` non funziona?

  4. Perché Deis e che cos'è?

  5. Perché sed fallisce con i caratteri internazionali e come risolverlo?

Che cos'è il comando Grep in Linux? Perché viene utilizzato e come funziona?

Quando viene gestito un segnale e perché alcune informazioni si bloccano?

Perché il mio sistema mostra solo 3,2 GiB di RAM quando ho sicuramente 4,0 GiB

Perché debian e ubuntu hanno come impostazione predefinita il runlevel 2?

Perché i numeri di chiamata del sistema Linux in x86 e x86_64 sono diversi?

Cosa fa 'set -e' e perché potrebbe essere considerato pericoloso?