2012-09-19 51 views
5

Soy muy nuevo en estos conceptos, pero quiero hacerte una pregunta que es muy básica, creo, pero estoy confundido, así que lo estoy preguntando. La pregunta es ... ¿Cómo es el tamaño de un proceso determinado por el sistema operativo? Déjeme aclararlo primero, supongamos que he escrito un programa en C y quiero saber cuánta memoria va a tomar, ¿cómo puedo determinarlo? en segundo lugar, sé que hay muchas secciones, como la sección de códigos, la sección de datos, el BSS de un proceso. Ahora, ¿el tamaño de estos está predeterminado? segundo, cómo se determina el tamaño de Stack y Heap. el tamaño de la pila y el montón también importa mientras se calcula el tamaño total del proceso.¿Cómo se determina el tamaño del proceso?

Nuevamente decimos que cuando cargamos el programa, se da un espacio de direcciones al proceso (que se realiza por base y registro de límite y controlado por MMU, supongo) y cuando el proceso intenta acceder a una ubicación de memoria no está en su espacio de direcciones obtenemos falla de segmentación. ¿Cómo es posible que un proceso acceda a una memoria que no está en su espacio de direcciones? De acuerdo con mi entendimiento, cuando ocurren desbordamientos de búfer, la dirección se corrompe. Ahora cuando el proceso quiere acceder a la ubicación dañada, obtenemos el error de segmentación. ¿Hay alguna otra forma de violación de la dirección?

y en tercer lugar por qué la pila crece hacia abajo y se acumula hacia arriba. Este proceso es el mismo con todo el sistema operativo. ¿Cómo afecta el rendimiento? ¿Por qué no podemos tenerlo de otra manera?

Corrija esta respuesta, si me equivoco en alguna de las declaraciones.

Gracias Sohrab

+0

No es una pregunta de programación. – unwind

Respuesta

1

Cuando se inicia un proceso, obtiene su propio espacio de direcciones virtuales. El tamaño del espacio de direcciones virtuales depende de su sistema operativo. En general, los procesos de 32 bits obtienen 4 direcciones GiB (4 giga binarias) y los procesos de 64 bits obtienen 18 direcciones Eib (18 exa binarias).

No puede acceder de ninguna manera a nada que no esté mapeado en su espacio de direcciones virtuales ya que, por definición, todo lo que no esté mapeado no tiene una dirección para usted. Puede intentar acceder a las áreas de su espacio de direcciones virtuales que actualmente no están asignadas a nada, en cuyo caso obtendrá una excepción segfault.

No todo el espacio de direcciones está asignado a algo en un momento dado. Además, no todo el mapa puede correlacionarse (la cantidad de mapeo depende del procesador y del sistema operativo). En la generación actual de procesadores Intel, se pueden mapear hasta 256 TiB de su espacio de direcciones. Tenga en cuenta que los sistemas operativos pueden limitarlo aún más. Por ejemplo, para procesos de 32 bits (que tienen hasta 4 direcciones GiB) Windows por defecto reserva 2 GiB para el sistema y 2 GiB para la aplicación (pero hay una manera de hacerlo 1 GiB para el sistema y 3 GiB para la aplicación).

La cantidad de espacio de direcciones que se usa y la cantidad asignada cambia mientras se ejecuta la aplicación. Las herramientas específicas del sistema operativo le permitirán monitorear lo que la memoria asignada actualmente y el espacio de direcciones virtuales es para una aplicación que se está ejecutando.

Sección de código, sección de datos, BSS, etc. son términos que hacen referencia a diferentes áreas del archivo ejecutable creado por el vinculador. En general, el código está separado de los datos estáticos inmutables que están separados de los datos asignados estáticamente pero mutables. La pila y el montón están separados de todos los anteriores. Su tamaño es calculado por el compilador y el enlazador. Tenga en cuenta que cada archivo binario tiene sus propias secciones, por lo que las bibliotecas vinculadas dinámicamente se correlacionarán en el espacio de direcciones por separado, cada una con sus propias secciones asignadas en algún lugar. El montón y la pila, sin embargo, no son parte de la imagen binaria, generalmente hay solo una pila por proceso y un montón.

El tamaño de la pila (al menos la pila inicial) generalmente es fijo. Los compiladores y/o vinculadores generalmente tienen algunos indicadores que puede usar para establecer el tamaño de la pila que desea en tiempo de ejecución. Las pilas generalmente "crecen hacia atrás" porque así es como funcionan las instrucciones de la pila de procesadores. Si las pilas crecen en una dirección y el resto crece en la otra, es más fácil organizar la memoria en situaciones en las que desea que ambas sean ilimitadas, pero no se sabe cuánto puede crecer cada una.

El montón, en general, se refiere a todo lo que no está preasignado cuando se inicia el proceso. En el nivel más bajo hay varias operaciones lógicas relacionadas con la gestión de heap (no todas se implementan como describo aquí en todos los sistemas operativos).

Si bien el espacio de direcciones es fijo, algunos sistemas operativos realizan un seguimiento de las partes que el proceso recupera actualmente. Incluso si este no es el caso, el proceso en sí necesita hacer un seguimiento de ello. Por lo tanto, la operación de nivel más bajo es realmente decidir que se usará una cierta región del espacio de direcciones.

La segunda operación de bajo nivel es instruir al sistema operativo para asignar esa región a algo.Esto, en general, puede ser

  • parte de la memoria que no es intercambiable en

  • memoria que es intercambiable y se asigna al archivo de intercambio del sistema

  • memoria que es intercambiable y se asigna a algún otro archivo

  • memoria que se puede cambiar y mapear a algún otro archivo en modo de solo lectura

  • la misma asignación que otra región de direcciones virtuales se asigna a

  • la misma asignación que otra región de direcciones virtuales se asigna a, pero en modo de sólo lectura

  • la misma asignación que otra región de direcciones virtuales se asigna a , pero en la copia en el modo de escritura con los datos copiados asignados al archivo de intercambio por defecto

puede haber otras combinaciones se me olvidó, pero esos son los principales.

Por supuesto, el espacio total utilizado realmente depende de cómo lo defina. La RAM que se usa actualmente es diferente al espacio de direcciones actualmente mapeado. Pero como escribí anteriormente, las herramientas que dependen del sistema operativo deberían permitirle descubrir lo que está sucediendo actualmente.

1

Las secciones están predeterminados por el archivo ejecutable.

Además de aquél, pueden existir las bibliotecas dinámicamente vinculadas. Si bien se supone que el código y los datos constantes de un archivo DLL se comparten en varios procesos que lo utilizan y no se cuentan más de una vez, sus datos no constantes específicos del proceso se deben tener en cuenta en cada proceso.

Además, puede haber memoria dinámicamente asignada en el proceso.

Además, si hay múltiples hilos en el proceso, cada uno de ellos tendrá su propia pila.

Además, habrá estructuras de datos por subproceso, por proceso y por biblioteca en el proceso y en el kernel en su nombre (almacenamiento local de subprocesos, parámetros de línea de comandos, identificadores de diversos recursos , estructuras para esos recursos también y así sucesivamente).

Es difícil calcular el tamaño completo del proceso exactamente sin saber cómo se implementa todo. Sin embargo, puede obtener una estimación razonable.

W.r.t. According to my understanding when some buffer overflows happens then the address gets corrupted. No es necesariamente cierto. Antes que nada, ¿la dirección de qué? Depende de lo que sucede en la memoria cerca del buffer. Si hay una dirección, puede sobreescribirse durante un desbordamiento del búfer. Pero si hay otro búfer cerca que contiene una imagen de usted, los píxeles de la imagen pueden sobreescribirse.

Puede obtener errores de segmentación o de página al intentar acceder a la memoria para la que no tiene los permisos necesarios (por ejemplo, la parte del kernel mapeada o presente en el espacio de direcciones de proceso). O puede ser una ubicación de solo lectura. O la ubicación no puede tener una asignación a la memoria física.

Es difícil saber cómo la ubicación y el diseño de la pila y el montón afectarán el rendimiento sin conocer el rendimiento de lo que estamos hablando. Puedes especular, pero las especulaciones pueden ser incorrectas.

Por cierto, realmente debería considerar hacer preguntas por separado en SO para temas separados.

+0

gracias ... lo tendré en cuenta la próxima vez ...: -) ... gracias por la explicación. –

1

"¿Cómo es posible que un proceso acceda a una memoria que no está en su espacio de direcciones?"

Dada la protección de la memoria es imposible. Pero podría ser intentado. Considere punteros aleatorios o acceda más allá de los almacenamientos intermedios. Si incrementa cualquier puntero el tiempo suficiente, es casi seguro que entra en un rango de direcciones no asignado. Ejemplo simple:

char *p = "some string"; 

while (*p++ != 256) /* Always true. Keeps incrementing p until segfault. */ 
    ; 

Los errores simples como este no son inauditos, para subestimar.

+1

Se llama "litotes". :) – Mehrdad

+0

Gracias! No odio completamente aprender este tipo de terminología :-) – Jens

0

Respondo las preguntas n. ° 2 y n. ° 3.

respuesta # 2

Cuando en C que utiliza punteros que realmente está utilizando un valor numérico que se interpreta como la dirección de memoria (dirección lógica en el sistema operativo moderno, véanse las notas). Puede modificar esta dirección a su voluntad. Si el valor apunta a una dirección que no está en su espacio de direcciones, tiene su falla de segmentación.

Considere por ejemplo este escenario: su sistema operativo le da a su proceso el rango de direcciones de 0x01000 a 0x09000. Entonces

int * ptr = 0x01000; 
printf("%d", ptr[0]); // * prints 4 bytes (sizeof(int) bytes) of your address space 
int * ptr = 0x09100; 
printf("%d", ptr[0]); // * You are accessing out of your space: segfault 

Sobre todo las causas de la violación de segmento, como usted ha señalado, son el uso de punteros a NULL (que es sobre todo la dirección 0x00, pero depende de la implementación) o el uso de direcciones dañados.

Tenga en cuenta que, en Linux i386, el registro base y el límite no se utilizan como usted piensa. No son límites por proceso, pero apuntan a dos tipos de segmentos: espacio de usuario o espacio de kernel.

respuesta # 3

El crecimiento de la pila depende del hardware y no depende del sistema operativo. En i386 las instrucciones de ensamblaje, como push y pop, hacen que la pila crezca hacia abajo con respecto a los registros relacionados con la pila. Por ejemplo, el puntero de la pila disminuye automáticamente cuando haces un push, y aumenta cuando haces un pop. OS no puede lidiar con eso.

Notas al pie

En un sistema operativo moderno, un proceso utiliza la denominada dirección de la lógica. Esta dirección se asigna con la dirección física por el sistema operativo. Para tener una nota de este mismo compilar este programa simplemente:

#include <stdio.h> 

int main() 
{ 
    int a = 10; 
    printf("%p\n", &a); 
    return 0; 
} 

Si ejecuta este programa varias veces (incluso de forma simultánea) se podría ver, incluso para diferentes casos, la misma dirección se imprime. Por supuesto, esta no es la dirección de memoria real, pero es una dirección lógica que se asignará a la dirección física cuando sea necesario.

Cuestiones relacionadas