2010-02-08 17 views

Respuesta

5

Esa pregunta depende del número de variables utilizadas. Como no especificaste qué compilador o lenguaje o incluso el sistema operativo, ¡es difícil definirlo! Todo depende del sistema operativo que es responsable de la administración de la memoria de las aplicaciones. En resumen, no hay una respuesta definitiva a esta pregunta, piense en esto, el compilador/enlazador en tiempo de ejecución, solicita al sistema operativo que asigne un bloque de memoria, esa asignación depende de cuántas variables hay, qué tan grandes son, el alcance y uso de las variables. Por ejemplo, este programa simple en C, en un archivo llamado simpletest.c:

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

Suponiendo que el medio ambiente se basa en Unix/Linux y fue compilado como esto:

 
gcc -o simpletest simpletest.c 

Si se va a emitir un objdump o nm en la imagen binaria simpletest, verá las secciones del ejecutable, en este caso, 'bss', 'texto'. Tome nota de los tamaños de estas secciones, ahora agregue un int var[100]; al código anterior, recompile y vuelva a emitir el objdump o nm, encontrará que ha aparecido la sección data, ¿por qué? porque agregamos una variable de un tipo de matriz de int, con 100 elementos.

Este ejercicio simple demostrará que las secciones crecen y, por lo tanto, el binario se agranda, y también demostrará que no puede predeterminar cuánta memoria se asignará, ya que la implementación en tiempo de ejecución varía de compilador a compilador y de funcionamiento sistema a sistema operativo.

En resumen, el sistema operativo llama a la gestión de memoria.

1

se puede obtener toda esta información de compilar el programa

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

y luego 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 

la salida muestra la estructura general de hola. El primer encabezado del programa corresponde al segmento de código del proceso, que se cargará desde el archivo en el offset 0x000000 en una región de memoria que se mapeará en el espacio de direcciones del proceso en la dirección 0x08048000. El segmento de código tendrá un tamaño de 0x55dac y debe estar alineado con la página (0x1000). Este segmento comprenderá los segmentos ELF de .text y .rodata discutidos anteriormente, más segmentos adicionales generados durante el procedimiento de vinculación. Como se esperaba, está marcado como de solo lectura (R) y ejecutable (X), pero no puede escribirse (W).

El segundo encabezado de programa corresponde al segmento de datos del proceso. Cargando este segmento sigue los mismos pasos mencionados anteriormente. Sin embargo, tenga en cuenta que el tamaño del segmento es 0x01df4 en el archivo y 0x03240 en la memoria. Esto se debe a la sección .bss, que debe ponerse a cero y, por lo tanto, no es necesario que esté presente en el archivo. El segmento de datos también estará alineado con la página (0x1000) y contendrá los segmentos .data y .bss ELF. Se marcará legible y escribible (RW). El tercer encabezado del programa resulta del procedimiento de enlace y es irrelevante para esta discusión.

Si usted tiene un sistema de ficheros proc, se puede comprobar esto, siempre y cuando se obtiene "Hello World" para ejecutar el tiempo suficiente (pista: BGF), con el siguiente 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 primera la región mapeada es el segmento de código del proceso, la segunda y la tercera compilación del segmento de datos (datos + bss + montón), y la cuarta, que no tiene correspondencia en el archivo ELF, es la pila. Se puede obtener información adicional sobre el proceso de ejecución hola con tiempo GNU, ps y/proc/pid/stat.

ejemplo tomado de:

+0

Gracias por el tutorial detallado! Sin embargo, me queda un acertijo: ¿cómo determinaste que el primer encabezado del programa correspondía al segmento de código del proceso y el segundo a su segmento de datos? ¿Convención? ¿El hecho de que uno es RO (huele a .code) y el otro es RW? (¿Qué pasa si hay dos RO o dos secciones de RW?) – U007D

+0

Sí, es una regla, y también el primer segmento está marcado como ejecutable, por lo que debe ser __code__. – 4pie0

Cuestiones relacionadas