2010-02-08 22 views
5

Segmenti di memoria - BSS, Stack, Heap, Dati, Codice/Testo (ce ne sono altri?).BSS, Stack, Heap, dati, codice/testo - dove ognuno di questi inizia in memoria?

dice che ho un 128 MB di RAM, Qualcuno può dirmi:

  • Quanta memoria viene allocata per ognuno di questi segmenti di memoria?

  • Da dove iniziano? Si prega di specificare l'intervallo di indirizzi o qualcosa del genere per una migliore chiarezza.

  • Quali fattori influenzano quali dovrebbero iniziare dove?

risposta

5

Questa domanda dipende dal numero di variabili utilizzate. Dato che non hai specificato quale compilatore o linguaggio o sistema operativo, è difficile da definire! Tutto dipende dal sistema operativo responsabile della gestione della memoria delle applicazioni. In breve, non esiste una risposta definitiva a questa domanda, pensate a questo, il compilatore/linker in fase di esecuzione, richiede al sistema operativo di allocare un blocco di memoria, che l'allocazione dipende da quante variabili ci sono, quanto sono grandi, la portata e l'uso delle variabili. Per esempio, questo semplice programma C, in un file chiamato simpletest.c:

 
#include <stdio.h> 
int main(int argc, char **argv){ 
    int num = 42; 
    printf("The number is %d!\n", num); 
    return 0; 
} 

Supponendo l'ambiente si è basata Unix/Linux ed è stato compilato in questo modo:

 
gcc -o simpletest simpletest.c 

Se si dovesse emettere un objdump o nm sull'immagine binaria simpletest, vedrai le sezioni dell'eseguibile, in questo caso, 'bss', 'testo'. Prendi nota delle dimensioni di queste sezioni, ora aggiungi un codice int var[100]; al codice sopra, ricompila e riemetti lo objdump o nm, troverai che la sezione data è apparsa - perché? perché abbiamo aggiunto una variabile di un tipo di array di int, con 100 elementi.

Questo semplice esercizio dimostrerà che le sezioni crescono, e quindi il binario si ingrandisce, e dimostrerà anche che non è possibile stabilire quale quantità di memoria verrà allocata poiché l'implementazione del runtime varia dal compilatore al compilatore e dal funzionamento sistema al sistema operativo.

In breve, il sistema operativo chiama lo scatto sulla gestione della memoria!

1

è possibile ottenere tutte queste informazioni compilare il programma

# gcc -o hello hello.c // you might compile with -static for simplicity 

e poi readelf:

# readelf -l hello 
Elf file type is EXEC (Executable file) 
Entry point 0x80480e0 
There are 3 program headers, starting at offset 52 

Program Headers: 
    Type   Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 
    LOAD   0x000000 0x08048000 0x08048000 0x55dac 0x55dac R E 0x1000 
    LOAD   0x055dc0 0x0809edc0 0x0809edc0 0x01df4 0x03240 RW 0x1000 
    NOTE   0x000094 0x08048094 0x08048094 0x00020 0x00020 R 0x4 

Section to Segment mapping: 
    Segment Sections... 
    00  .init .text .fini .rodata __libc_atexit __libc_subfreeres .note.ABI-tag 
    01  .data .eh_frame .got .bss 
    02  .note.ABI-tag 

L'uscita mostra la struttura complessiva del ciao. La prima intestazione del programma corrisponde al segmento di codice del processo, che verrà caricato dal file all'offset 0x000000 in un'area di memoria che verrà mappata nello spazio indirizzo del processo all'indirizzo 0x08048000. Il segmento di codice sarà di byte 0x55dac di grandi dimensioni e deve essere allineato alla pagina (0x1000). Questo segmento comprenderà i segmenti ELF di .text e .rodata discussi in precedenza, più i segmenti aggiuntivi generati durante la procedura di collegamento. Come previsto, è contrassegnato come di sola lettura (R) ed eseguibile (X), ma non modificabile (W).

L'intestazione del secondo programma corrisponde al segmento di dati del processo. Il caricamento di questo segmento segue gli stessi passaggi sopra menzionati. Tuttavia, si noti che la dimensione del segmento è 0x01df4 su file e 0x03240 in memoria. Ciò è dovuto alla sezione .bss, che deve essere azzerata e quindi non deve essere presente nel file. Anche il segmento dati sarà allineato alla pagina (0x1000) e conterrà i segmenti ELF. Date e .BSS. Sarà contrassegnato come leggibile e scrivibile (RW). L'intestazione del terzo programma risulta dalla procedura di collegamento ed è irrilevante per questa discussione.

Se si dispone di un file system proc, è possibile controllare questo, fino a quando si ottiene "Ciao Mondo" per funzionare abbastanza a lungo (suggerimento: gdb), con il seguente comando:

# cat /proc/`ps -C hello -o pid=`/maps 
08048000-0809e000 r-xp 00000000 03:06 479202  .../hello 
0809e000-080a1000 rw-p 00055000 03:06 479202  .../hello 
080a1000-080a3000 rwxp 00000000 00:00 0 
bffff000-c0000000 rwxp 00000000 00:00 0 

La prima la regione mappata è il segmento di codice del processo, il secondo e il terzo creano il segmento di dati (dati + bss + heap) e il quarto, che non ha corrispondenza nel file ELF, è lo stack. Ulteriori informazioni sul processo hello in esecuzione possono essere ottenute con GNU time, ps e/proc/pid/stat.

esempio tratto da:

+0

Grazie per la procedura dettagliata dettagliata! Tuttavia, rimane un problema per me: come hai stabilito che la prima intestazione del programma corrispondeva al segmento di codice del processo e la seconda al suo segmento di dati? Convenzione? Il fatto che uno sia RO (odori come .code) e l'altro è RW? (Cosa succede se c'erano due sezioni RO o due RW?) – U007D

+0

Sì, è una regola, e anche il primo segmento è contrassegnato come eseguibile, quindi questo deve essere __code__. – 4pie0

Problemi correlati