In che modo le dimensioni dello stack e dell'heap sono limitate dal sistema operativo?

17

Nota : se devi considerare un sistema operativo specifico per poter rispondere, considera Linux.

Ogni volta che eseguo un programma, verrà dato uno spazio di memoria virtuale per l'esecuzione, con un'area per il suo stack e uno per il suo heap.

Domanda 1 : lo stack e l'heap hanno un limite di dimensioni statiche (ad esempio, 2 gigabyte ciascuno), oppure è un limite dinamico, che varia in base alle allocazioni di memoria durante l'esecuzione del programma (ad esempio, 4 gigabyte totali da utilizzare da entrambi, quindi se un programma utilizza solo lo stack, sarà in grado di avere uno stack con 4 gigabyte)?

Domanda 2 : come viene definito il limite? È la memoria RAM disponibile totale?

Domanda 3 : per quanto riguarda le sezioni di testo (codice) e dati, come sono limitate?

    
posta Daniel Scocco 06.08.2013 - 15:51
fonte

2 risposte

20

Ci sono due limiti di memoria differenti. Il limite di memoria virtuale e il limite di memoria fisica.

Memoria virtuale

La memoria virtuale è limitata dalle dimensioni e dal layout dello spazio degli indirizzi disponibile. Di solito all'inizio sono il codice eseguibile ei dati statici e il passato che fa crescere l'heap, mentre alla fine è l'area riservata dal kernel, prima delle librerie e dello stack condivisi (che nella maggior parte delle piattaforme diminuisce). Ciò consente di aumentare lo spazio libero di heap e stack, mentre le altre aree vengono riconosciute all'avvio del processo e corrette.

La memoria virtuale libera non è inizialmente contrassegnata come utilizzabile, ma è contrassegnata come tale durante l'allocazione. Mentre l'heap può crescere in tutta la memoria disponibile, la maggior parte dei sistemi non accumula automaticamente stack. Il limite predefinito di IIRC per stack è 8MiB su Linux e 1MiB su Windows e può essere modificato su entrambi i sistemi. La memoria virtuale contiene anche file e hardware mappati in memoria.

Uno dei motivi per cui lo stack non può essere auto-cresciuto (arbitrariamente) è che i programmi multi-thread richiedono uno stack separato per ogni thread, quindi alla fine si intrometteranno.

Sulle piattaforme a 32 bit la quantità totale di memoria virtuale è 4GiB, sia Linux che Windows che normalmente riservano l'ultimo 1GiB per il kernel, offrendoti al massimo 3GiB di spazio degli indirizzi. C'è una versione speciale di Linux che non riserva nulla dandoti un 4GiB completo. È utile per il raro caso di database di grandi dimensioni in cui l'ultimo 1GiB salva il giorno, ma per un uso regolare è leggermente più lento a causa del ricarico della tabella di pagine aggiuntivo.

Su piattaforme a 64 bit la memoria virtuale è 64EiB e non devi pensarci.

Memoria fisica

Solitamente la memoria fisica viene allocata dal sistema operativo solo quando il processo deve accedervi. La quantità di memoria fisica utilizzata da un processo è molto sfocata, in quanto parte della memoria è condivisa tra processi (codice, librerie condivise e qualsiasi altro file mappato), i dati dei file vengono caricati in memoria su richiesta e scartati in caso di mancanza di memoria e La memoria "anonima" (quella non supportata dai file) può essere scambiata.

Su Linux, ciò che accade quando si esaurisce la memoria fisica dipende dall'impostazione di sistema vm.overcommit_memory . L'impostazione predefinita è l'overcommit. Quando chiedi al sistema di allocare memoria, ne fornisce alcuni, ma assegna solo la memoria virtuale. Quando accedi effettivamente alla memoria, cercherà di utilizzare la memoria fisica, scartando i dati che possono essere riletti o scambiati, se necessario. Se trova che non può liberare nulla, rimuoverà semplicemente il processo dall'esistenza (non c'è modo di reagire, perché quella reazione potrebbe richiedere più memoria e ciò porterebbe a un ciclo infinito).

Questo è il modo in cui i processi muoiono su Android (che è anche Linux). La logica è stata migliorata con il processo che logico di rimuovere dall'esistenza in base a ciò che sta facendo il processo e quanti anni ha. I processi Android semplicemente smettono di fare qualsiasi cosa, ma siediti in background e il "killer esaurito" li ucciderà quando ha bisogno di memoria per i nuovi.

    
risposta data 06.08.2013 - 16:17
fonte
9

Penso che sia più facile rispondere a questo in base all'ordine di utilizzo della memoria.

Domanda 3: per quanto riguarda le sezioni di testo (codice) e dati, come sono limitate? Testo e dati sono preparati dal compilatore. Il requisito per il compilatore è assicurarsi che siano accessibili e comprimerli nella parte inferiore dello spazio degli indirizzi. Lo spazio di indirizzi accessibile sarà limitato dall'hardware, ad es. se il registro del puntatore di istruzioni è a 32 bit, lo spazio di indirizzamento del testo sarà 4 GiB.

Domanda 2: come viene definito il limite? È la memoria RAM disponibile totale? Dopo il testo e i dati, l'area sopra è l'heap. Con la memoria virtuale, l'heap può praticamente crescere su vicino allo spazio di indirizzi massimo.

Domanda 1: lo stack e l'heap hanno un limite di dimensioni statiche (ad esempio, 2 gigabyte ciascuno), oppure è un limite dinamico, che varia in base alle allocazioni di memoria durante l'esecuzione del programma (ad esempio, 4 gigabyte totale da utilizzare da entrambi, quindi se un programma utilizza solo lo stack, sarà in grado di avere uno stack con 4 gigabyte)? Il segmento finale nello spazio di indirizzamento del processo è lo stack. Lo stack prende il segmento finale dello spazio indirizzo e inizia dalla fine e cresce giù .

Poiché l'heap cresce e lo stack si riduce, si limitano sostanzialmente a vicenda. Inoltre, poiché entrambi i tipi di segmenti sono scrivibili, non è sempre stata una violazione per uno di essi superare il limite, pertanto è possibile che si verifichi un overflow del buffer o dello stack. Ora ci sono meccanismi per impedire che si verifichino.

C'è un limite impostato per heap (stack) per ogni processo con cui iniziare. Questo limite può essere modificato in fase di esecuzione (usando brk () / sbrk ()). In pratica, ciò che accade è quando il processo ha bisogno di più spazio su heap e ha esaurito lo spazio allocato, la libreria standard invierà la chiamata al sistema operativo. Il sistema operativo assegnerà una pagina, che di solito sarà gestita dalla libreria utente per il programma da utilizzare. Cioè se il programma richiede 1 KiB, il sistema operativo fornirà 4 KiB aggiuntivi e la libreria darà 1 KiB al programma e lascerà 3 KiB da utilizzare quando il programma chiederà altri risultati la prossima volta.

La maggior parte delle volte il layout sarà Text, Data, Heap (cresce), spazio non allocato e infine Stack (cresce). Condividono tutti lo stesso spazio degli indirizzi.

    
risposta data 06.08.2013 - 17:22
fonte

Leggi altre domande sui tag