Isso não é verdade em "quase todos os sistemas operacionais". Os tipos de memória representados são bastante típicos, mas não há razão para que eles devam estar em uma ordem específica, e pode haver mais de uma peça de um determinado tipo.
No Linux, você pode ver o espaço de endereço de um processo com cat /proc/$pid/maps
, em que $pid
é o ID do processo, por exemplo, cat /proc/$$/maps
para ver o shell do qual você está executando cat
ou cat /proc/self/maps
para ver os mapeamentos do próprio cat
. O comando pmap
produz resultados ligeiramente mais agradáveis.
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]
Você pode ver o código e os dados de leitura / gravação (texto e BSS) do executável, em seguida, o heap, depois um arquivo mapeado na memória e, em seguida, um pouco mais de dados de leitura e gravação e dados de somente leitura. e ler / gravar dados de uma biblioteca compartilhada (texto e BSS novamente), mais dados de leitura e gravação, outra biblioteca compartilhada (mais precisamente, o vinculador dinâmico) e, finalmente, a pilha do único encadeamento.
O código do kernel usa seus próprios intervalos de endereços. Em muitas plataformas, o Linux usa a parte superior do espaço de endereço do kernel, geralmente o 1GB superior. Idealmente, esse espaço seria suficiente para mapear o código do kernel, os dados do kernel e a memória do sistema (RAM) e todos os dispositivos mapeados na memória. Em PCs de 32 bits típicos de hoje, isso não é possível, o que requer contorções que são de interesse apenas dos hackers do kernel.
Enquanto o código do kernel está lidando com uma chamada de sistema, idealmente (quando as contorções acima mencionadas não estão no lugar), a memória do processo é mapeada nos mesmos endereços. Isso permite que os processos passem dados para o kernel, e o kernel pode ler diretamente do ponteiro. No entanto, não é um grande ganho, já que os ponteiros precisam ser validados de qualquer maneira (para que o processo não consiga enganar o kernel para ler da memória que o processo não deveria ter acesso).
As zonas de memória dentro do espaço do kernel do Linux são bastante complexas. Existem vários pools de memória diferentes, e as principais distinções não são sobre onde a memória vem, mas sim com quem ela é compartilhada. Se você está curioso sobre eles, comece com LDD3 .