-
Debes haber leído algunos libros muy antiguos porque nadie programa para modo real más;-) En modo real , puede obtener la dirección física de un acceso a la memoria con
phyical address = segment register * 0x10 + offset
, siendo el desplazamiento un valor dentro de uno de los registros de uso general. Debido a que estos registros tienen un ancho de 16 bits, un segmento tendrá una longitud de 64 kb y no hay nada que pueda hacer con respecto a su tamaño, ¡solo porque no hay atributo! Con el* 0x10
multiplicación, 1mb de memoria disponible, pero hay combinaciones superpuestas dependiendo de lo que coloque en los registros de segmento y el registro de direcciones . No he compilado ningún código para modo real , pero creo que depende del sistema operativo configurar los registros de segmento durante la carga binaria, al igual que un cargador asignaría algunas páginas al cargar un binario ELF. Sin embargo, he compilado el código del núcleo sin sistema operativo y tuve que configurar estos registros por mí mismo. -
Cuatro segmentos son obligatorios en el modelo plano debido a las limitaciones de la arquitectura. En modo protegido los registros de segmento ya no contiene la dirección base del segmento, sino un selector de segmento que es básicamente una compensación en el GDT. Según el valor del selector de segmento , la CPU estará en un determinado nivel de privilegio, este es el CPL (Current Privilege Level). El selector de segmentos apunta a un descriptor de segmento que tiene un DPL (Nivel de privilegio de descriptor), que eventualmente es el CPL si el registro de segmento se llena con este selector (al menos cierto para el selector de segmento de código). Por lo tanto, necesita al menos un par de selectores de segmento para diferenciar el núcleo de la zona de usuario. Además, los segmentos son segmentos de código o segmentos de datos, por lo que eventualmente terminará con cuatro descriptores de segmento en la GDT.
-
No tengo ningún ejemplo de sistema operativo serio que haga uso de la segmentación, solo porque la segmentación todavía está presente para el cumplimiento hacia atrás. Usar el enfoque del modelo plano no es más que un medio para deshacerse de él. De todos modos, tiene razón, la paginación es mucho más eficiente y versátil, y está disponible en casi todas las arquitecturas (al menos en los conceptos). No puedo explicar aquí los aspectos internos de la paginación, pero toda la información que necesita saber está dentro del excelente hombre de Intel:Manual del desarrollador de software de arquitecturas Intel® 64 e IA-32 Volumen 3A:Guía de programación del sistema, Parte 1
Ampliando la respuesta de Benoit a la pregunta 3...
La división de programas en partes lógicas como código, datos constantes, datos modificables y pila la realizan diferentes agentes en diferentes momentos.
Primero, su compilador (y enlazador) crea archivos ejecutables donde se especifica esta división. Si observa una serie de formatos de archivos ejecutables (PE, ELF, etc.), verá que admiten algún tipo de secciones o segmentos o como quiera llamarlo. Además de las direcciones, los tamaños y las ubicaciones dentro del archivo, esas secciones tienen atributos que le indican al sistema operativo el propósito de estas secciones, p. esta sección contiene código (y aquí está el punto de entrada), esto:datos constantes inicializados, eso:datos no inicializados (por lo general, no ocupan espacio en el archivo), aquí hay algo sobre la pila, allí está la lista de dependencias (por ejemplo, DLL), etc.
Luego, cuando el sistema operativo comienza a ejecutar el programa, analiza el archivo para ver cuánta memoria necesita el programa, dónde y qué protección de memoria se necesita para cada sección. Esto último se hace comúnmente a través de tablas de páginas. Las páginas de códigos se marcan como ejecutables y de solo lectura, las páginas de datos constantes se marcan como no ejecutables y de solo lectura, otras páginas de datos (incluidas las de la pila) se marcan como no ejecutables y de lectura y escritura. Así es como debería ser normalmente.
Muchas veces los programas necesitan regiones de lectura-escritura y, al mismo tiempo, ejecutables para el código generado dinámicamente o simplemente para poder modificar el código existente. El acceso RWX combinado puede especificarse en el archivo ejecutable o solicitarse en tiempo de ejecución.
Puede haber otras páginas especiales, como páginas de protección para la expansión dinámica de la pila, se colocan junto a las páginas de la pila. Por ejemplo, su programa comienza con suficientes páginas asignadas para una pila de 64 KB y luego, cuando el programa intenta acceder más allá de ese punto, el sistema operativo intercepta el acceso a esas páginas de protección, asigna más páginas para la pila (hasta el tamaño máximo admitido) y mueve las páginas de protección aún más. Estas páginas no necesitan especificarse en el archivo ejecutable, el sistema operativo puede manejarlas por sí solo. El archivo solo debe especificar los tamaños de pila y quizás la ubicación.
Si no hay hardware o código en el sistema operativo para distinguir la memoria de código de la memoria de datos o para hacer cumplir los derechos de acceso a la memoria, la división es muy formal. Los programas DOS en modo real de 16 bits (COM y EXE) no tenían códigos, datos ni segmentos de pila marcados de alguna manera especial. Los programas COM tenían todo en un segmento común de 64 KB y comenzaban con IP=0x100 y SP=0xFFxx y el orden del código y los datos podía ser arbitrario en el interior, podían entrelazarse prácticamente libremente. Los archivos DOS EXE solo especificaban las ubicaciones iniciales de CS:IP y SS:SP y más allá de eso, el código, los datos y los segmentos de la pila eran indistinguibles para DOS. Todo lo que necesitaba hacer era cargar el archivo, realizar la reubicación (solo para EXE), configurar el PSP (prefijo de segmento de programa, que contiene el parámetro de la línea de comando y alguna otra información de control), cargar SS:SP y CS:IP. No pudo proteger la memoria porque la protección de la memoria no está disponible en el modo de dirección real, por lo que los formatos ejecutables de DOS de 16 bits eran muy simples.