2010-08-08 24 views
13

He tomado un curso sobre el diseño y el concepto del sistema operativo y ahora estoy tratando de estudiar el kernel de Linux a fondo. Tengo una pregunta de la que no me puedo deshacer. En los sistemas operativos modernos, cada proceso tiene espacio de direcciones virtuales (VAS) propio (por ejemplo, de 0 a 2^32-1 en sistemas de 32 bits). Esto proporciona muchas ventajas. Pero en la implementación estoy confundido en algunos puntos. Permítanme explicarlo dando un ejemplo:¿Cómo se asignan las mismas direcciones virtuales para diferentes procesos a diferentes direcciones físicas?

Digamos que tenemos dos procesos p1, p2; p1 y p2 tienen sus propios VAS. Una dirección 0x023f4a54 está asignada a diferentes direcciones físicas (PA), ¿cómo puede ser? ¿Cómo se hace esta traducción de esta manera? Quiero decir que conozco el mecanismo de traducción, pero no puedo entender que la misma dirección esté asignada a una dirección física diferente cuando se trata de espacio de direcciones de procesos diferentes.

0x023f4a54 in p1's VAS => PA 0x12321321 
0x023f4a54 in p2's VAS => PA 0x23af2341 # (random addresses) 
+0

https://en.wikipedia.org/wiki/Virtual_memory –

Respuesta

3

Gracias por todas las respuestas. El verdadero punto que no sé es que la misma dirección virtual de los diferentes procesos no entra en conflicto con el corresponsal físico del otro. Encontré la respuesta en el siguiente enlace, cada proceso tiene su propia tabla de páginas.

http://tldp.org/LDP/tlk/mm/memory.html

6

Su pregunta confunde una dirección virtual con el uso de una dirección como una forma de identificación, por lo que el primer paso para entender es separar los conceptos.

Un ejemplo de trabajo es la función de biblioteca C runtime sprintf(). Cuando se declara y se llama correctamente, se incorpora a un programa como un módulo de objeto compartido, junto con todas las funciones secundarias que necesita. La dirección de sprintf varía de programa a programa porque la biblioteca está cargada en una dirección libre disponible. Para un simple hello world programa, sprintf puede cargarse en la dirección 0x101000. Para un programa complejo que calcula impuestos, puede cargarse en 0x763f8000 (debido a toda la lógica asquerosa que contiene el programa principal va antes que las bibliotecas a las que hace referencia). Desde la perspectiva del sistema, la biblioteca compartida se carga en la memoria en un solo lugar, pero la ventana de direcciones (rango de direcciones) que cada proceso ve que la memoria es exclusiva de ese ejecutable.

Por supuesto, esto se complica aún más por algunas de las características de Security Enhanced Linux (SELinux) que aleatoriza las direcciones en las que se cargan diferentes secciones de programa en la memoria, incluida la asignación de biblioteca compartida.

--- --- aclaración Como alguien señala correctamente, el mapeo de direcciones virtuales de cada proceso es específico para cada proceso, no a diferencia de su conjunto de descriptores de archivos, conexiones de socket, padres y niños proceso, etc. Eso es decir, p1 puede asignar la dirección 0x1000 al físico 0x710000 mientras que p2 asigna la dirección 0x1000 a un error de página, y p3 se asigna a alguna biblioteca compartida en física 0x9f32a000. La asignación de direcciones virtuales es cuidadosamente supervisada por el sistema operativo, posiblemente para proporcionar características tales como intercambio y paginación, pero también para proporcionar características como códigos y datos compartidos, y datos compartidos entre procesos.

+0

Mi problema no es acerca de compartir. El problema es que cuando p1 intenta alcanzar VA 0x04 este VA se traduce a una dirección física, entonces ocurre el cambio de contexto y otro proceso p2 intenta alcanzar el mismo VA 0x04. Este VA se traslada a otra dirección física pero no puede ser igual con p1. ¿Cómo puede ser esta diferencia provista por el sistema operativo? Se pueden alcanzar los mismos VA pero estos VA no están asignados a la misma dirección física. Me pregunto el mecanismo más allá de ese problema de traducción. ¿Cómo impide el sistema operativo que estos procesos choquen entre sí? – dirtybit

+2

@Pushdown Como se mencionó, el sistema operativo mantiene un mapeo separado por proceso, y intercambia esas mapeos cuando cambia entre los procesos. – nos

22

Una CPU que proporciona memoria virtual le permite configurar una asignación de las direcciones de memoria a medida que la CPU la ve con direcciones de memoria física, generalmente esto se hace mediante una unidad de hardware llamada MMU.

El núcleo del sistema operativo puede programar esa MMU, generalmente no en las direcciones individuales, sino en unidades de páginas (4096 bytes es común). Esto significa que la MMU puede programarse para traducir, p. las direcciones virtuales 0x1000-0x2000 se traducirán a la dirección física 0x20000-0x21000.

El sistema operativo mantiene un conjunto de estas asignaciones por proceso, y antes de programar un proceso para que se ejecute, carga esa asignación en la MMU antes de volver a cambiar el control al proceso. Esto permite diferentes asignaciones para diferentes procesos, y nada impide que esas asignaciones mapeen la misma dirección virtual en una dirección física diferente.

Todo esto es transparente en lo que respecta al programa, simplemente ejecuta instrucciones en la CPU, y como la CPU se ha configurado en modo de memoria virtual (modo paginado), cada acceso de memoria es traducido por la MMU antes sale en el bus físico a la memoria.

Los detalles de implementación reales son complicados, pero aquí hay algunas referencias que pueden proporcionar más información;

+2

Por cierto, gracias por el libro gorman. Es muy bueno, de hecho. – dirtybit

1

Este mapeo (dirección virtual a la dirección física) es manejado por el sistema operativo y la MMU (véase la respuesta @nos'); El objetivo de esta abstracción es que p1 "piensa" que está accediendo al 0x023f4a54 cuando en realidad está accediendo al 0x12321321.

Si vuelve a su clase sobre cómo funcionan los programas en el nivel de código de máquina, p1 esperará que alguna variable/función/lo que sea esté en el mismo lugar (p. Ej. 0x023f4a54) cada vez que se cargue. La asignación de la dirección física a virtual del sistema operativo proporciona esta abstracción. En realidad, no siempre se cargará en la misma dirección física ,, pero a su programa no le importa, siempre que esté en la misma dirección virtual.

+2

Los * internos mágicos * son los MMU (hardware en realidad, no el sistema operativo), vea la respuesta de nos. El sistema operativo decide el mapeo y programa la MMU para implementar realmente la traducción. – Wim

5

Hay dos estructuras de datos importantes que se ocupan de la paginación: la tabla de páginas y la TLB. El sistema operativo mantiene diferentes tablas de páginas por proceso. El TLB es solo un caché de la tabla de páginas.

Ahora, diferentes CPU son, bueno, diferentes. x86 accede directamente a las tablas de páginas, usando un registro especial llamado CR3 que apunta a la tabla de páginas en uso. Los procesadores MIPS no saben nada sobre la tabla de páginas, por lo que el sistema operativo debe trabajar directamente con el TLB.

Algunas CPU (por ejemplo: MIPS) mantienen un identificador en el TLB para separar los diferentes procesos, por lo que el sistema operativo puede cambiar un registro de control al hacer un cambio de contexto (a menos que sea necesario reutilizar un identificador). Otras CPU requieren un lavado completo de TLB en cada cambio de contexto. Entonces, básicamente, el sistema operativo necesita cambiar algunos registros de control y posiblemente necesite borrar el TLB (realizar un lavado de TLB) para permitir que las direcciones virtuales de diferentes procesos se correlacionen con las direcciones físicas que deberían.

Cuestiones relacionadas