La segmentación de memoria es una técnica de gestión de memoria del sistema operativo que consiste en dividir la memoria principal de una computadora en segmentos o secciones . En un sistema informático que utiliza la segmentación, una referencia a una ubicación de memoria incluye un valor que identifica un segmento y un desplazamiento (ubicación de memoria) dentro de ese segmento. Los segmentos o secciones también se utilizan en archivos de objetos de programas compilados cuando se vinculan entre sí en una imagen de programa y cuando la imagen se carga en la memoria.
Los segmentos suelen corresponder a divisiones naturales de un programa, como rutinas individuales o tablas de datos [1], por lo que la segmentación suele ser más visible para el programador que la paginación sola. [2] Los segmentos pueden crearse para módulos de programa o para clases de uso de memoria, como segmentos de código y segmentos de datos . [3] Ciertos segmentos pueden compartirse entre programas. [1] [2]
La segmentación se inventó originalmente como un método mediante el cual el software del sistema podía aislar los procesos de software ( tareas ) y los datos que utilizaban. Su objetivo era aumentar la confiabilidad de los sistemas que ejecutaban múltiples procesos simultáneamente. [4]
En un sistema que utiliza segmentación, las direcciones de memoria de la computadora consisten en un identificador de segmento y un desplazamiento dentro del segmento. [3] Una unidad de administración de memoria de hardware (MMU) es responsable de traducir el segmento y el desplazamiento a una dirección física y de realizar verificaciones para asegurarse de que se pueda realizar la traducción y que se permita la referencia a ese segmento y desplazamiento.
Cada segmento tiene una longitud y un conjunto de permisos (por ejemplo, lectura , escritura , ejecución ) asociados. [3] Un proceso solo puede hacer una referencia a un segmento si el tipo de referencia está permitido por los permisos y si el desplazamiento dentro del segmento está dentro del rango especificado por la longitud del segmento. De lo contrario, se genera una excepción de hardware, como un fallo de segmentación .
Los segmentos también se pueden utilizar para implementar la memoria virtual . En este caso, cada segmento tiene un indicador asociado que indica si está presente en la memoria principal o no. Si se accede a un segmento que no está presente en la memoria principal, se genera una excepción y el sistema operativo leerá el segmento en la memoria desde el almacenamiento secundario.
La segmentación es un método para implementar la protección de la memoria . [5] La paginación es otro método, y pueden combinarse. El tamaño de un segmento de memoria generalmente no es fijo y puede ser tan pequeño como un solo byte . [6]
La segmentación se ha implementado de varias formas en distintos tipos de hardware, con o sin paginación. La segmentación de memoria Intel x86 no se adapta a ninguno de los dos modelos y se analiza por separado a continuación y también con mayor detalle en un artículo aparte.
A cada segmento se asocia información que indica dónde se encuentra el segmento en la memoria: la base del segmento . Cuando un programa hace referencia a una ubicación de memoria, el desplazamiento se suma a la base del segmento para generar una dirección de memoria física.
Una implementación de memoria virtual en un sistema que utiliza segmentación sin paginación requiere que segmentos enteros se intercambien entre la memoria principal y el almacenamiento secundario. Cuando se intercambia un segmento, el sistema operativo tiene que asignar suficiente memoria libre contigua para albergar el segmento completo. A menudo, se produce fragmentación de la memoria si no hay suficiente memoria contigua, aunque pueda haber suficiente en total.
En lugar de una ubicación de memoria, la información del segmento incluye la dirección de una tabla de páginas para el segmento. Cuando un programa hace referencia a una ubicación de memoria, el desplazamiento se traduce a una dirección de memoria mediante la tabla de páginas. Un segmento se puede ampliar asignando otra página de memoria y añadiéndola a la tabla de páginas del segmento.
Una implementación de memoria virtual en un sistema que utiliza segmentación con paginación generalmente solo mueve páginas individuales de un lado a otro entre la memoria principal y el almacenamiento secundario, de manera similar a un sistema paginado no segmentado. Las páginas del segmento pueden ubicarse en cualquier lugar de la memoria principal y no necesitan ser contiguas. Esto generalmente da como resultado una cantidad reducida de entrada/salida entre el almacenamiento primario y secundario y una fragmentación de memoria reducida.
El ordenador B5000 de Burroughs Corporation fue uno de los primeros en implementar la segmentación y "quizás el primer ordenador comercial en proporcionar memoria virtual" [7] basada en la segmentación. El B5000 está equipado con una tabla de información de segmentos llamada Tabla de referencia de programa (PRT) que se utiliza para indicar si el segmento correspondiente reside en la memoria principal, para mantener la dirección base y el tamaño del segmento. [8] El ordenador B6500 posterior también implementó la segmentación; una versión de su arquitectura todavía se utiliza hoy en día en los servidores Unisys ClearPath Libra. [ cita requerida ]
La computadora GE 645 , una modificación de la GE-635 con soporte de segmentación y paginación agregado, fue diseñada en 1964 para soportar Multics .
El Intel iAPX 432 , [9] iniciado en 1975, intentó implementar una verdadera arquitectura segmentada con protección de memoria en un microprocesador.
La versión 960MX de los procesadores Intel i960 admitía instrucciones de carga y almacenamiento con el origen o destino siendo un "descriptor de acceso" para un objeto, y un desplazamiento dentro del objeto, con el descriptor de acceso estando en un registro de 32 bits y con el desplazamiento calculado a partir de un desplazamiento base en el siguiente registro y a partir de un desplazamiento adicional y, opcionalmente, un registro de índice especificado en la instrucción. Un descriptor de acceso contiene bits de permiso y un índice de objeto de 26 bits; el índice de objeto es un índice dentro de una tabla de descriptores de objeto, dando un tipo de objeto, una longitud de objeto y una dirección física para los datos del objeto, una tabla de páginas para el objeto, o la tabla de páginas de nivel superior para una tabla de páginas de dos niveles para el objeto, dependiendo del tipo de objeto. [10]
Las computadoras Prime , Stratus , Apollo , IBM System/38 y IBM AS/400 (incluido IBM i ) utilizan segmentación de memoria.
Las palabras en los modelos B5000, B5500 y B5700 tienen una longitud de 48 bits. [11] Los descriptores tienen el bit superior establecido en la palabra. Residen en la tabla de referencia de programa (PRT) o en la pila, y contienen un bit de presencia que indica si los datos están presentes en la memoria. Hay descriptores de datos y de programa distintos. [11] : 4-2–4-4
Las palabras en el B6500 y sus sucesores tienen 48 bits de datos y 3 bits de etiqueta. [12] : 2-1 Los bits de etiqueta indican el tipo de datos contenidos en la palabra; hay varios tipos de descriptores, indicados por diferentes valores de bits de etiqueta. [12] : 6-5–6-10 La línea incluye el B6500, B6700, B7700, B6800, B6900, B5900, las máquinas Burroughs y Unisys de la serie A y los sistemas Clearpath MCP actuales (Libra). Si bien ha habido algunas mejoras a lo largo de los años, particularmente avances de hardware, la arquitectura ha cambiado poco. El esquema de segmentación se ha mantenido igual, consulte Memoria segmentada .
En los modelos IBM System/370 [a] con almacenamiento virtual [13] [14] (DAT) y direcciones de 24 bits, el registro de control 0 especifica un tamaño de segmento de 64 KiB o 1 MiB y un tamaño de página de 2 KiB o 4 KiB; el registro de control 1 contiene un Designador de tabla de segmentos (STD), que especifica la longitud y la dirección real de la tabla de segmentos. Cada entrada de la tabla de segmentos contiene una ubicación de la tabla de páginas, una longitud de la tabla de páginas y un bit no válido. Posteriormente, IBM amplió el tamaño de la dirección a 31 bits y agregó dos bits a las entradas de la tabla de segmentos:
Cada una de las implementaciones de DAT de IBM incluye una caché de traducción, que IBM llama Translation Lookaside Buffer (TLB). Si bien en Principles of Operation se analiza el TLB en términos generales, los detalles no forman parte de la arquitectura y varían de un modelo a otro.
A partir de los complejos de procesadores 3031, 3032 y 3033 , IBM ofreció una característica llamada Dual-address Space [14] : 5-13–5-17, Dual-Address-Space Control : 5-17–5-20, DAS Authorization Mechanisms : 5-21–5-24, PC-Number Translation [15] (DAS), que permite a un programa cambiar entre las tablas de traducción para dos espacios de direcciones, denominados espacio de direcciones primario (CR1) y espacio de direcciones secundario (CR7), y mover datos entre los espacios de direcciones sujetos a la clave de protección. DAS admite una tabla de traducción para convertir un número de espacio de direcciones (ASN) de 16 bits en un STD, con instrucciones privilegiadas para cargar el STD en CR1 (primario) o CR7 (secundario).
Los primeros procesadores x86 , comenzando con el Intel 8086 , proporcionan una segmentación de memoria rudimentaria y no ofrecen protección de memoria (cada byte de cada segmento está siempre disponible para cualquier programa). Los registros de segmento de 16 bits permiten 65.536 segmentos; cada segmento comienza en un desplazamiento fijo igual a 16 veces el número de segmento; la granularidad de la dirección de inicio del segmento es de 16 bytes. Cada segmento otorga acceso de lectura y escritura a 64 KiB (65.536 bytes) de espacio de direcciones (este límite lo establecen los registros PC y SP de 16 bits; el procesador no realiza ninguna comprobación de límites). El desplazamiento+dirección que excede 0xFFFFF vuelve a 0x00000. Cada segmento de 64 KiB se superpone a los siguientes 4.095 segmentos; cada dirección física puede denotarse mediante 4.096 pares segmento-desplazamiento. Este esquema puede manejar solo 1 MiB (1024 KiB) de memoria física (y E/S asignada a memoria). ( El hardware de memoria expandida opcional puede agregar memoria conmutada por bancos bajo control de software). Intel denominó retroactivamente " modo real " al único modo operativo de estos modelos de CPU x86 .
Los procesadores Intel 80286 y posteriores añaden el " modo protegido 286 ", que conserva el direccionamiento de 16 bits y añade segmentación (sin paginación) y protección de memoria por segmento. Para la compatibilidad con versiones anteriores, todas las CPU x86 se inician en "modo real", con los mismos segmentos fijos superpuestos de 64 KiB, sin protección de memoria, solo 1 MiB de espacio de dirección física y algunas diferencias sutiles ( área de memoria alta , modo irreal ). Para utilizar todo su espacio de dirección física de 24 bits (16 MiB) y las características avanzadas de MMU , un procesador 80286 o posterior debe cambiarse al "modo protegido" mediante software, normalmente el sistema operativo o un extensor de DOS . Si un programa no utiliza los registros de segmento, o solo pone en ellos valores que recibe del sistema operativo, entonces se puede ejecutar código idéntico en modo real o modo protegido, pero la mayoría del software de modo real calcula nuevos valores para los registros de segmento, lo que rompe esta compatibilidad.
Los procesadores Intel i386 y posteriores añaden el " modo protegido 386 ", que utiliza direccionamiento de 32 bits, conserva la segmentación y añade paginación de memoria . En estos procesadores, la tabla de segmentos, en lugar de apuntar a una tabla de páginas para el segmento, contiene la dirección del segmento en la memoria lineal . Cuando la paginación está habilitada, las direcciones en la memoria lineal se asignan a direcciones físicas utilizando una tabla de páginas separada. La mayoría de los sistemas operativos no utilizaban la capacidad de segmentación, optando por mantener la dirección base en todos los registros de segmento igual a 0 en todo momento y proporcionar protección de memoria por página e intercambio utilizando solo paginación. Algunos utilizan el registro CS para proporcionar protección de espacio ejecutable en procesadores que carecen del bit NX o utilizan los registros FS o GS para acceder al almacenamiento local de subprocesos. [16] [17]
La arquitectura x86-64 no admite la segmentación en " modo largo " (modo de 64 bits). [18] Cuatro de los registros de segmento: CS, SS, DS y ES se fuerzan a 0 y el límite a 2 64 . Los registros de segmento FS y GS aún pueden tener una dirección base distinta de cero. Esto permite que los sistemas operativos utilicen estos segmentos para fines especiales, como el almacenamiento local de subprocesos. [16] [17]