Materia: #organizacion_del_computador_II
Tags: Memoria, Segmentación y paginación
Descriptores de segmento
Cuando tenemos una memoria que funciona bajo el modelo de segmentación tenemos que tener en cuenta como se representan las direcciones de dicha memoria. En particular, las direcciones de un segmento consisten en dos partes escenciales: el selector de segmento, y un offset. A esa dirección la llamaremos dirección lógica.
El selector de segmento nos indicara en que porcion de la memoria tenemos que buscar. Generalmente se representa como un numero de 16 bits, permitiendonos representar a lo sumo 64K de tamaño. El offset, por otro lado, consiste en un numero entre 0 y el tamaño del segmento en cuestion. Se comporta como un indice en una lista, permitiendo acceder al dato especifico que se esta buscando dentro del segmento. Si el offset es 0, entonces se esta haciendo referencia a la dirección en la que el segmento empieza. En la maquina de Intel 64, el offset consiste en 64 bits.
Ahora bien, la magia del selector de segmento consiste en que nos indica el segmento pero en base a una tabla: la GDT (Global Descriptor Table). Es decir, el selector de segmento tambien se comporta como un indice, igual al offset, pero para indicarnos que segmento se esta buscando en base a una tabla que tiene descriptores de segmento.
Los descriptores de segmento, como su nombre indica, son secuencias de bits que nos brindan información del segmento en cuestión. Nos indican parte de su dirección real (a la que tambien llamamos dirección lineal), aparte de otros datos como los permisos que se necesitan para acceder, si se puede leer o escribir, si se encuentra presente (es decir, disponible), entre otros datos.
El descriptor de segmento mas de cerca se ve asi:
Donde:
-
Dirección base: Es la dirección a partir de la cual se despliega en forma continua el segmento.
-
Límite: El límite de un segmento especifica el máximo offset que puede tener un byte direccionable dentro del segmento. Suele confundirse este concepto con el tamaño del segmento. En realidad, el límite es el tamaño del segmento menos 1, ya que el offset del primer byte del segmento es 0.
-
G: De granularidad, establece la unidad de medida del campo Lı́mite. Si
, el máximo offset de un byte es igual a Lı́mite . Si , el máximo offset es igual a . -
D/B: Default / Big (Predeterminado o grande, en inglés). Configura el tamaño de los segmentos. Si es
, (Default) el segmento es de 16 bits. Si es , (Big) es un segmento de 32 bits. Para segmentos de código, implica que el tamaño de datos es de 16 bits u 8 bits, y el de direcciones de 16 bits. Si en cambio , el tamaño de un offset es 32 bits y el de los operandos es de 32 bits u 8 bits. En ambos casos mediante los prefijos de instrucción y respectivamente podemos alterar los defaults. En el caso de un segmento de datos utilizado como pila, si las operaciones de la pila son de 16 bits, aunque el operando de la instrucción sea de 8 bits. , son de 32 bits independientemente del tamaño del operando. El valor tope del segmento será también consecuencia del valor de este bit. -
L: El procesador solo mira este bit en el Modo IA-32e. Si en un segmento de código este bit es
, indica que el segmento contiene código nativo de 64 bits, caso contrario, ejecutará en Modo Compatibilidad. En modo IA-32e, si es , entonces D/B debe estar en . Si el procesador no está en modo IA-32e, o si está en este modo pero el segmento no es de código, el bit debe estar siempre en . -
AVL: AVaiLable (Disponible, en inglés). Este bit no es usado por el procesador para ningún propósito especı́fico. Queda para que el programador de sistemas le asigne el uso que considere mas apropiado.
-
P: De presente, cuando es
el segmento correspondiente está presente en la memoria RAM. Si es , el segmento está en la memoria virtual (disco). Un acceso a un segmento cuyo bit está en , genera una excepción NP (Segmento No Presente). Esto permite al kernel solucionar el problema, efectuando el “swap” entre el disco a memoria para ponerlo accesiible en RAM. -
A: De accedido, se setea cada vez que se accede una dirección en el segmento. Permite al Sistema Operativo contabilizar los accesos para elaborar estadı́sticas de uso que permitan identificar cual es el segmento a ser desalojado llegado el momento.
-
DPL: Descriptor Priviledge Level. Nivel de privilegio que debe tener el segmento que contiene el código que pretende acceder a éste segmento.
-
S: De sistema, este bit, activo bajo permite administrar en las tablas de descriptores, dos clases bien determinadas de segmentos:
-
Segmentos de código o datos.
-
Segmentos de sistema. Tienen diferentes formatos y en general no se refieren a zonas de memoria (salvo TSS). En general se refieren a mecanismos de uso de recursos del procesador por parte del kernel (por ello reciben el nombre de descriptores de Sistema, ya que son para uso exclusivo del Sistema Operativo)
-
-
Bit 11: En este caso el bit 11 define si el segmento correspondiente a este descriptor es de código o de datos, según valga
o respectivamente. En cada caso los dos bits subsiguientes tienen un significado diferente. -
C: De conforming, significa ajustable. Estos segmentos de código “ajustan” su nivel de privilegio al del código que los ha invocado. Permiten que un segmento de código pueda ser invocado desde otro segmento de código menos privilegiado mediante por ejemplo una instrucción
CALL
a una subrutina residente en este segmento. Sin embargo el código privilegiado ajustará su nivel de privilegio al del segmento de código invocante. -
R: De readable (legible, en inglés). Este bit habilita cuando es
la lectura de direcciones de memoria residente en el segmento. En general se usa cuando se tienen constantes en el segmento que necesitan ser accedidas para su lectura. Si el segmento solo tiene código, puede ponerse en el descriptor para prevenir que se pueda leer cualquier ı́tem de este segmento utilizando el prefijo CS
en la instrucción para modificar el comportamiento del procesador en la asignación por default del registro de segmento en el modo de direccionamiento empleado. -
ED: De expand down (crecer hacia abajo, en inglés). Cuando el segmento de datos va a ser utilizado como pila, puede optarse por tratarlo como un segmento común de datos, o definirlo como expand down, poniendo de manifiesto que es una pila, y su puntero de direcciones decrece hacia las direcciones de memoria numéricamente menores a medida que se expande el segmento (de allı́ el término Expand Down).
-
W: De writable (escribible, en inglés). Este bit, indica si el segmento de datos puede escribirse. Si este bit está en
, el segmento contiene datos pero es Read Only.
En la practica, para poder abarcar toda la memoria se implementa la idea de LDT (o Local Descriptor Table). Es decir, la GDT ya no guarda descriptores de segmentos, lo que guarda son descriptores de tablas locales de segmentos, donde a su vez se guardan los descriptores de segmento para poder encontrar la dirección lineal.
Los descriptores de segmento y los descriptores de tablas de segmento como tal no tienen mucha diferencia. Lo mas notable es que en el bit 11, justo despues del bit de sistema, tienen 4 bits donde se les declara un tipo acorde a la siguiente tabla:
11 | 10 | 9 | 8 | Modo 32 bits |
---|---|---|---|---|
0 | 0 | 0 | 0 | Reservado |
0 | 0 | 0 | 1 | TSS de 16 bits disponible |
0 | 0 | 1 | 0 | LDT |
0 | 0 | 1 | 1 | TSS de 16 bits busy |
0 | 1 | 0 | 0 | Call gate de 16 bits |
0 | 1 | 0 | 1 | Task gate |
0 | 1 | 1 | 0 | Interrupt gate de 16 bits |
0 | 1 | 1 | 1 | Trap gate de 16 bits |
1 | 0 | 0 | 0 | Reservado |
1 | 0 | 0 | 1 | TSS de 32 bits disponible |
1 | 0 | 1 | 0 | Reservado |
1 | 0 | 1 | 1 | TSS de 32 bits busy |
1 | 1 | 0 | 0 | Call gate de 32 bits |
1 | 1 | 0 | 1 | Reservado |
1 | 1 | 1 | 0 | Interrupt gate de 32 bits |
1 | 1 | 1 | 1 | Trap gate de 32 bits |