Pregunta

Es un hecho conocido que las aplicaciones de Windows suelen tener 2 GB de espacio de direcciones privadas en un sistema de 32 bits. Este espacio se puede extender a 3 Gb con el modificador / 3GB.

El sistema operativo se reserva el restante del 4 Gb.

Mi pregunta es ¿Por qué?

código que se ejecuta en modo de núcleo (es decir, código de controlador de dispositivo) tiene su propio espacio de direcciones. ¿Por qué, en la parte superior de un exclusivo espacio de direcciones de 4 GB, el sistema operativo todavía quiere reservar 2 Gb de cada proceso en modo de usuario?

pensé que la razón es la transición entre el modo de usuario y modo kernel llamada. Por ejemplo, una llamada a NtWriteFile necesitará una dirección para la rutina de envío de núcleo (de ahí por qué el sistema de reserva de 2 Gb en cada aplicación). Sin embargo, el uso de SYSENTER, no es el número de servicio al sistema suficiente para que el código en modo kernel para saber qué función / servicio está siendo llamado?

Si pudiera aclarar a mí por qué es tan importante para el sistema operativo para tomar de 2 Gb (o 1 Gb) de cada proceso en modo de usuario.

¿Fue útil?

Solución

Hay dos procesos diferentes usuarios tienen diferentes espacios de direcciones virtuales. Debido a que las asignaciones de dirección virtual↔physical son diferentes, el caché TLB se invalida cuando se cambia contextos de un usuario proceso a otro. Esto es muy caro, ya que sin la dirección ya en caché en el TLB, cualquier acceso a memoria se traducirá en una falta y un paseo de la PTE s.

llamadas al sistema implican dos cambios de contexto: el usuario → kernel, y luego kernel → usuario. Con el fin de acelerar este proceso, es común a reservar el de 1 GB o superior 2 GB de espacio de direcciones virtuales para el uso del kernel. Debido a que el espacio de direcciones virtuales no cambia a través de estos cambios de contexto, sin rubores TLB son necesarios. Esto es posible por un bit de usuario / supervisor a cada PTE, que asegura que la memoria del núcleo sólo se puede acceder mientras que en el kernelspace; el espacio de usuario no tiene acceso a pesar de que la tabla de páginas es la misma.

Si no hubiera soporte de hardware para dos TLB separadas, con una exclusiva para el uso del kernel, esta optimización ya no sería útil. Sin embargo, si usted tiene suficiente espacio para dedicar, es probable que sea más la pena hacer sólo uno más grande TLB.

Linux en x86, una vez apoyó un modo conocido como "4G / 4G dividir". En este modo, el espacio de usuario tiene acceso completo a todo el espacio de direcciones virtuales de 4 GB, y el núcleo también tiene un espacio de direcciones virtuales de 4 GB completa. El costo, como se mencionó anteriormente, es que todos syscall requiere un rubor TLB, junto con rutinas más complejas para copiar datos entre el usuario y la memoria del núcleo. Esto ha sido medida para imponer hasta una penalización de rendimiento 30%.


Los tiempos han cambiado desde que esta pregunta se formuló originalmente y respondió: sistemas operativos de 64 bits son ahora mucho más frecuente. En los sistemas operativos actuales en x86-64, direcciones virtuales de 0 a 2 47 -1 (0-128TB) están permitidos para programas de usuario, mientras que el núcleo reside en forma permanente dentro de las direcciones virtuales a partir de 2 47 × (2 17 -1) a 2 64 -1 (o desde -2 47 a -1, si el tratamiento de direcciones como enteros con signo).

¿Qué ocurre si se ejecuta un ejecutable de 32 bits en Windows de 64 bits? Se podría pensar que todas las direcciones virtuales de 0 a 2 32 (0-4GB) sería fácilmente disponible, pero con el fin de evitar la exposición de los errores en los programas existentes, ejecutables de 32 bits todavía se limitan a 0- 2 GB a menos que se vuelven a compilar con /LARGEADDRESSAWARE. Para aquellos que son, consiguen el acceso a 0-4GB. (Esto no es una nueva bandera, y lo mismo se aplica en los núcleos de Windows de 32 bits que se ejecutan con el interruptor /3GB, que cambió la 2G / 2G de usuario / kernel de división de valor a 3G / 1G, aunque por supuesto 3-4GB todavía estaría fuera de rango.)

¿Qué tipo de errores pueden surgir? A modo de ejemplo, supongamos que está implementando la clasificación rápida y tienen dos punteros, a y señalando b al principio y más allá del final de una matriz. Si elige el medio como el pivote con (a+b)/2, funcionará siempre y cuando ambas direcciones están por debajo de los 2 GB, pero si son tanto más arriba, entonces la adición se encontrará con desbordamiento de entero y el resultado estará fuera de la matriz. (La expresión correcta es a+(b-a)/2.)

Como un programas de lado, Linux de 32 bits, con su 3G / 1G usuario / kernel de división de valor, ha funcionado históricamente con su pila se encuentra en el rango 2-3GB, por lo que cualquier tipo de errores de programación probablemente habría de ser expulsadas rápidamente . Linux de 64 bits da acceso a programas de 32 bits a 0-4GB.

Otros consejos

Windows (como cualquier sistema operativo) es mucho más que el kernel + conductores.

Su aplicación se basa en una gran cantidad de servicios del sistema operativo que no sólo existen en el espacio del núcleo. Hay una gran cantidad de tampones, mangos y todo tipo de recursos que pueden quedar asignados a propio espacio de direcciones del proceso. Cada vez que se llama a una función de Win32 API que devuelve, por ejemplo, un identificador de ventana, o un cepillo, esas cosas tienen que ser asignados en alguna parte de su proceso. Así que parte de Windows se ejecuta en el kernel, sí, otras partes se ejecutan en sus propios procesos en modo usuario, y algunos, los que su aplicación necesita acceso directo, se asignan a su espacio de direcciones. Parte de esto es difícil de evitar, pero un factor adicional importante es el rendimiento. Si todos Win32 llamada requiere un cambio de contexto, sería una actuación golpe importante. Si algunos de ellos se pueden manejar en modo de usuario, porque los datos se basan en ya está asignada a su espacio de direcciones, se evita el cambio de contexto, y ahorrar unos cuantos ciclos de CPU.

Así que cualquier necesidad de utilizar una cierta cantidad del espacio de direcciones a un lado. Creo Linux por defecto sólo conjuntos de 1 GB para el sistema operativo.

La razón por la MS se estableció en 2 GB con Windows se explicó en el blog de Raymond Chen vez. No tengo el enlace, y no puedo recordar los detalles, pero la decisión fue tomada debido a que Windows NT fue apuntado inicialmente en procesadores Alpha también, y sobre el Alpha de, había un poco de buena razón para hacer el 50/50 división. ;)

Era algo que ver con el apoyo del Alfa de 32, así como el código de 64 bits. :)

  

código que se ejecuta en modo de núcleo (es decir, código de controlador de dispositivo) tiene su propio espacio de direcciones.

No, no lo hace. Se tiene que compartir ese espacio de direcciones con la parte de modo de usuario de un proceso en procesadores x86. Es por eso que el núcleo tienen que reservar espacio suficiente en total y finitas del espacio de direcciones.

Creo que la mejor respuesta es que los diseñadores del sistema operativo sentido que en el momento en que tendría que cuidar, la gente estaría utilizando Windows de 64 bits.

Pero aquí hay un mejor discusión .

Parte de la respuesta tiene que ver con la historia de las arquitecturas de microprocesador. Aquí hay algo de lo que sé, otros pueden proporcionar datos más recientes.

El procesador Intel 8086 tenía una arquitectura segmento-offset para la memoria, dando 20 direcciones de memoria de bits, y la memoria física direccionable por lo tanto total de 1 MB.

A diferencia de la competencia procesadores de la época - como el Zilog Z80 - Intel 8086 sólo tenía un espacio de direcciones que tenía para dar cabida no sólo memoria electrónica, pero todas las comunicaciones de entrada / salida con dichos periféricos de menor importancia como teclado, puertos serie, puertos de impresora y pantallas de vídeo. (En comparación, el Zilog Z80 tenía un espacio de direcciones de entrada / salida por separado con códigos de operación de ensamblaje dedicados para el acceso)

La necesidad de dejar espacio para una gama cada vez mayor de las expansiones periféricas llevado a la decisión original para segmentar el espacio de direcciones en la memoria electrónica del 0-640K, y "otras cosas" (entrada / salida, ROM, memoria de vídeo, etc.) de 640 KB a 1 MB.

A medida que la línea x86 creció y evolucionó, y las PC evolucionado con ellos, se han utilizado esquemas similares, hoy termina con 2G / 2G división del espacio de direcciones 4G.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top