Esto no es cierto para "casi todos los sistemas operativos". Los tipos de áreas de memoria representados son bastante típicos, pero no hay ninguna razón por la que deberían estar en un orden particular, y puede haber más de una pieza de un tipo determinado.
En Linux, puede ver el espacio de direcciones de un proceso con cat /proc/$pid/maps
dónde $pid
está la ID del proceso, por ejemplo, cat /proc/$$/maps
para ver el shell desde el que se está ejecutando cat
o cat /proc/self/maps
para ver las cat
asignaciones propias del proceso. El comando pmap
produce una salida ligeramente más agradable.
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]
Puede ver el código y los datos de lectura-escritura (texto y BSS) del ejecutable, luego el montón, luego un archivo mapeado en memoria, luego un poco más de datos de lectura-escritura, luego código, datos de solo lectura y lectura- escribe datos de una biblioteca compartida (texto y BSS nuevamente), más datos de lectura-escritura, otra biblioteca compartida (más precisamente, el enlazador dinámico) y finalmente la pila del único hilo.
El código del kernel usa sus propios rangos de direcciones. En muchas plataformas, Linux usa la parte superior del espacio de direcciones para el núcleo, a menudo el 1GB superior. Idealmente, este espacio sería suficiente para mapear el código del kernel, los datos del kernel y la memoria del sistema (RAM) y cada dispositivo mapeado en memoria. En las PC típicas de 32 bits de hoy en día, esto no es posible, lo que requiere contorsiones que solo son de interés para los piratas informáticos del kernel.
Mientras el código del kernel maneja una llamada del sistema, idealmente (cuando las contorsiones antes mencionadas no están en su lugar) la memoria del proceso se asigna a las mismas direcciones. Esto permite que los procesos pasen datos al núcleo, y el núcleo puede leer directamente desde el puntero. Sin embargo, no es una gran ganancia, ya que los punteros deben ser validados de todos modos (para que el proceso no pueda engañar al núcleo para que lea desde la memoria a la que no se supone que el proceso tenga acceso).
Las zonas de memoria dentro del espacio del kernel de Linux son bastante complejas. Hay varios grupos de memoria diferentes, y las principales distinciones no se refieren a la procedencia de la memoria sino a con quién se comparte. Si tiene curiosidad sobre ellos, comience con LDD3 .
where.c
, en Ubuntu 11.04 usandogcc where.c -o where
; informa "principal en 0x80483c4". Intentéreadelf -S where
, e informa, di "[13] .text PROGBITS 08048310 ..." que parece correcto? Aunque también obtengo "ac at 0xbfb035a0" y "local at 0xbfb0358c", y ese rango de direcciones (0xbf ...) parece no ser informado porreadelf -S
.ac
yav
la variable automáticalocal
probablemente tendrán diferentes direcciones en cada invocación. La mayoría de los núcleos modernos de Linux tienen "Aleatorización del diseño del espacio de direcciones" para dificultar la explotación de los desbordamientos del búfer.