stringtranslate.com

Tabla de descriptores globales

La tabla de descriptores globales ( GDT ) es una estructura de datos que utilizan los procesadores de la familia x86 de Intel a partir del 80286 para definir las características de las distintas áreas de memoria utilizadas durante la ejecución del programa, incluidas la dirección base, el tamaño y los privilegios de acceso, como la capacidad de ejecución y escritura. Estas áreas de memoria se denominan segmentos en la terminología de Intel.

Descripción

La GDT es una tabla de entradas de 8 bytes. Cada entrada puede hacer referencia a un descriptor de segmento , segmento de estado de tarea (TSS), tabla de descriptores locales (LDT) o puerta de llamada . Las puertas de llamada se diseñaron para transferir el control entre niveles de privilegio x86, aunque este mecanismo no se utiliza en la mayoría de los sistemas operativos modernos.

También existe una tabla de descriptores locales (LDT). Se pueden definir varias LDT en la GDT, pero solo una está vigente en cada momento: normalmente está asociada con la tarea actual. Mientras que la LDT contiene segmentos de memoria que son privados para un proceso específico, la GDT contiene segmentos globales. Los procesadores x86 tienen funciones para cambiar automáticamente la LDT actual en eventos específicos de la máquina, pero no tienen funciones para cambiar automáticamente la GDT.

Cada acceso a la memoria que realiza un proceso siempre pasa por un segmento. En el procesador 80386 y posteriores, debido a los límites y desplazamientos de segmento de 32 bits , es posible hacer que los segmentos cubran toda la memoria direccionable, lo que hace que el direccionamiento relativo al segmento sea transparente para el usuario.

Para hacer referencia a un segmento, un programa debe utilizar su índice dentro de la GDT o la LDT. Este índice se denomina selector de segmento (o selector). El selector debe cargarse en un registro de segmento para poder utilizarse. Aparte de las instrucciones de máquina que permiten establecer/obtener la posición de la GDT y de la Tabla de descriptores de interrupciones (IDT) en la memoria, cada instrucción de máquina que hace referencia a la memoria tiene un registro de segmento implícito, ocasionalmente dos. La mayoría de las veces, este registro de segmento se puede anular añadiendo un prefijo de segmento antes de la instrucción.

Al cargar un selector en un registro de segmento, se lee la entrada GDT o LDT en el momento en que se carga y se almacenan en caché las propiedades del segmento en un registro oculto. Las modificaciones posteriores al GDT o LDT no surtirán efecto hasta que se vuelva a cargar el registro de segmento.

Formato de un descriptor de segmento

GDT en 64 bits

El GDT todavía está presente en el modo de 64 bits; se debe definir un GDT, pero generalmente nunca se lo cambia ni se lo utiliza para segmentación. El tamaño del registro se ha ampliado de 48 a 80 bits, y los descriptores de 64 bits son siempre "planos" (por lo tanto, de 0x00000000000000000 a 0xFFFFFFFFFFFFFFFF). Sin embargo, la base de FS y GS no está restringida a 0, y continúan utilizándose como punteros al desplazamiento de elementos como el bloque de entorno de proceso y el bloque de información de subproceso.

Si se borra el bit del sistema (cuarto bit del campo de acceso), el tamaño del descriptor es de 16 bytes en lugar de 8. Esto se debe a que, aunque se ignoran los segmentos de código/datos, no se ignoran los TSS, pero el puntero TSS puede tener una longitud de 64 bits y, por lo tanto, el descriptor necesita más espacio para insertar la palabra clave superior del puntero TSS.

Las versiones de 64 bits de Windows no permiten conectar el GDT; intentar hacerlo provocará una comprobación de errores de la máquina . [1]

Tabla de descriptores locales

Una Tabla de Descriptores Locales ( LDT ) es una tabla de memoria utilizada en la arquitectura x86 en modo protegido y que contiene descriptores de segmentos de memoria , al igual que la GDT: dirección de inicio en memoria lineal, tamaño, ejecutabilidad, capacidad de escritura, privilegio de acceso, presencia real en memoria, etc.

Las LDT son hermanas de la tabla de descriptores globales (GDT) y cada una define hasta 8192 segmentos de memoria accesibles para los programas. Tenga en cuenta que, a diferencia de la GDT, la entrada cero es una entrada válida y se puede utilizar como cualquier otra entrada de LDT. Tenga en cuenta también que, a diferencia de la GDT, la LDT no se puede utilizar para almacenar determinadas entradas del sistema: TSS o LDT. Sin embargo, las puertas de llamada y las puertas de tarea sí lo son.

Historia

En los procesadores x86 que no tienen funciones de paginación, como el Intel 80286 , la LDT es esencial para implementar espacios de direcciones separados para múltiples procesos. Generalmente habrá una LDT por proceso de usuario, que describe la memoria privada, mientras que la memoria compartida y la memoria del kernel serán descritas por la GDT. El sistema operativo cambiará la LDT actual al programar un nuevo proceso, utilizando la instrucción de máquina LLDT o al utilizar un TSS . Por el contrario, la GDT generalmente no se cambia (aunque esto puede suceder si se ejecutan monitores de máquinas virtuales como VMware en la computadora).

La falta de simetría entre ambas tablas se ve subrayada por el hecho de que la LDT actual puede cambiarse automáticamente en determinados eventos, en particular si se utiliza la multitarea basada en TSS , mientras que esto no es posible para la GDT. La LDT tampoco puede almacenar ciertos tipos privilegiados de segmentos de memoria (por ejemplo, TSS). Finalmente, la LDT está definida en realidad por un descriptor dentro de la GDT, mientras que la GDT está definida directamente por una dirección lineal.

La creación de memoria compartida a través de la GDT tiene algunas desventajas. Cabe destacar que dicha memoria es visible para todos los procesos y tiene los mismos derechos. Para restringir la visibilidad y diferenciar la protección de la memoria compartida, por ejemplo para permitir solo el acceso de lectura para algunos procesos, se pueden utilizar entradas LDT independientes, que apunten a las mismas áreas de memoria física y que se creen solo en las LDT de los procesos que hayan solicitado acceso a un área de memoria compartida determinada.

Las entradas de LDT (y GDT) que apuntan a áreas de memoria idénticas se denominan alias . Los alias también se crean normalmente para obtener acceso de escritura a segmentos de código: no se puede utilizar un selector ejecutable para escribir. (Los programas en modo protegido construidos en el llamado modelo de memoria diminuta , donde todo se encuentra en el mismo segmento de memoria, deben utilizar selectores separados para código y datos/pila, lo que hace que ambos selectores sean técnicamente también "alias"). En el caso de GDT, también se crean alias para obtener acceso a segmentos del sistema como los TSS.

Los segmentos tienen una bandera "Presente" en sus descriptores, lo que permite eliminarlos de la memoria si surge la necesidad. Por ejemplo, los segmentos de código o los segmentos de datos no modificados se pueden descartar, y los segmentos de datos modificados se pueden intercambiar en el disco. Sin embargo, debido a que es necesario operar con segmentos enteros como una unidad, es necesario limitar su tamaño para garantizar que el intercambio pueda realizarse de manera oportuna. Sin embargo, el uso de segmentos más pequeños y más fáciles de intercambiar significa que los registros de segmento se deben recargar con mayor frecuencia, lo que en sí mismo es una operación que consume mucho tiempo.

Uso moderno

El microprocesador Intel 80386 introdujo la paginación , es decir, la asignación de páginas de memoria física independientes (que son unidades de memoria muy pequeñas) en las mismas direcciones virtuales, con la ventaja de que la paginación de disco es mucho más rápida y eficiente que el intercambio de segmentos. Por lo tanto, los sistemas operativos x86 de 32 bits modernos utilizan muy poco la LDT, principalmente para ejecutar código heredado de 16 bits .

Si se necesita ejecutar código de 16 bits en un entorno de 32 bits mientras se comparte memoria (esto sucede, por ejemplo, cuando se ejecutan programas de OS/2 1.x en OS/2 2.0 y posteriores), la LDT debe escribirse de tal manera que cada dirección plana (paginada) también tenga un selector en la LDT (normalmente esto da como resultado que la LDT se llene con entradas de 64 KiB). Esta técnica a veces se denomina mosaico de LDT . El tamaño limitado de la LDT significa que el espacio de dirección plana virtual debe limitarse a 512 megabytes (8191 veces 64 KiB); esto es lo que sucede en OS/2, aunque esta limitación se solucionó en la versión 4.5. También es necesario asegurarse de que los objetos asignados en el entorno de 32 bits no crucen los límites de 64 KiB; esto genera un desperdicio de espacio de direcciones.

Si el código de 32 bits no tiene que pasar objetos de memoria arbitrarios al código de 16 bits, por ejemplo presumiblemente en la emulación OS/2 1.x presente en Windows NT o en la capa de emulación de Windows 3.1 , no es necesario limitar artificialmente el tamaño del espacio de direcciones de 32 bits.

Referencias

  1. ^ "Política de parches para sistemas basados ​​en x64". 8 de octubre de 2009. Archivado desde el original el 19 de enero de 2022. Consultado el 11 de diciembre de 2020. Si el sistema operativo detecta una de estas modificaciones o cualquier otro parche no autorizado, generará una comprobación de errores y apagará el sistema.

Enlaces externos