Questo non è vero per "quasi tutti i sistemi operativi". I tipi di aree di memoria rappresentate sono abbastanza tipici, ma non c'è motivo per cui debbano essere in un ordine particolare e può esserci più di un pezzo di un determinato tipo.
Sotto Linux, puoi guardare lo spazio degli indirizzi di un processo con cat /proc/$pid/maps
dove si $pid
trova l'ID del processo, ad esempio cat /proc/$$/maps
per guardare la shell da cui stai eseguendo cat
o cat /proc/self/maps
per esaminare i cat
mapping propri del processo. Il comando pmap
produce un output leggermente più gradevole.
08048000-08054000 r-xp 00000000 08:01 828061 /bin/cat
08054000-08055000 r--p 0000b000 08:01 828061 /bin/cat
08055000-08056000 rw-p 0000c000 08:01 828061 /bin/cat
08c7f000-08ca0000 rw-p 00000000 00:00 0 [heap]
b755a000-b7599000 r--p 00000000 08:01 273200 /usr/lib/locale/en_US.utf8/LC_CTYPE
b7599000-b759a000 rw-p 00000000 00:00 0
b759a000-b76ed000 r-xp 00000000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76ed000-b76ee000 ---p 00153000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76ee000-b76f0000 r--p 00153000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76f0000-b76f1000 rw-p 00155000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76f1000-b76f4000 rw-p 00000000 00:00 0
b770b000-b7712000 r--s 00000000 08:01 271618 /usr/lib/gconv/gconv-modules.cache
b7712000-b7714000 rw-p 00000000 00:00 0
b7714000-b7715000 r-xp 00000000 00:00 0 [vdso]
b7715000-b7730000 r-xp 00000000 08:01 263049 /lib/ld-2.11.1.so
b7730000-b7731000 r--p 0001a000 08:01 263049 /lib/ld-2.11.1.so
b7731000-b7732000 rw-p 0001b000 08:01 263049 /lib/ld-2.11.1.so
bfbec000-bfc01000 rw-p 00000000 00:00 0 [stack]
Puoi vedere il codice e i dati di lettura-scrittura (testo e BSS) dall'eseguibile, quindi l'heap, quindi un file mappato in memoria, quindi un po 'più di dati di lettura-scrittura, quindi codice, dati di sola lettura e lettura- scrivere dati da una libreria condivisa (di nuovo testo e BSS), più dati di lettura-scrittura, un'altra libreria condivisa (più precisamente, il linker dinamico) e infine lo stack del thread unico.
Il codice del kernel utilizza i propri intervalli di indirizzi. Su molte piattaforme, Linux utilizza la parte superiore dello spazio degli indirizzi per il kernel, spesso la parte superiore da 1 GB. Idealmente, questo spazio sarebbe sufficiente per mappare il codice del kernel, i dati del kernel e la memoria di sistema (RAM) e ogni dispositivo mappato in memoria. Sui tipici PC a 32 bit di oggi, questo non è possibile, il che richiede contorsioni che interessano solo gli hacker del kernel.
Mentre il codice del kernel gestisce una chiamata di sistema, idealmente (quando le suddette contorsioni non sono presenti) la memoria del processo è mappata agli stessi indirizzi. Ciò consente ai processi di passare i dati al kernel e il kernel può leggere direttamente dal puntatore. Non è un grande vantaggio, tuttavia, poiché i puntatori devono comunque essere convalidati (in modo che il processo non possa indurre il kernel a leggere dalla memoria a cui il processo non dovrebbe avere accesso).
Le zone di memoria all'interno dello spazio del kernel Linux sono piuttosto complesse. Esistono diversi pool di memoria e le principali distinzioni non riguardano l'origine della memoria, ma piuttosto con chi è condivisa. Se sei curioso di conoscerli, inizia con LDD3 .
where.c
, usando Ubuntu 11.04gcc where.c -o where
; riporta "principale a 0x80483c4". Ho provatoreadelf -S where
, e riporta, dire "[13] .text PROGBITS 08048310 ..." che sembra giusto? Anche se ottengo anche "ac a 0xbfb035a0" e "local a 0xbfb0358c" e l'intervallo di indirizzi (0xbf ...) sembra non essere segnalato dareadelf -S
.