1. Qué vamos a simular
El simulador tiene una tabla de segmentos con 4 entradas. El usuario puede:
- Editar la base, el límite y los permisos (r, w, x) de cada segmento.
- Introducir una dirección lógica (segmento + desplazamiento).
- Ver el resultado de la traducción: dirección física o falla de protección.
- Ver el motivo de la falla (segmento inválido, fuera de rango, permiso denegado).
2. El programa de ejemplo
Este programa en C simula la traducción y protección con segmentación, incluyendo varios casos de falla:
#include <stdio.h>
typedef struct { unsigned long base, limite; int r, w, x; } Seg;
static const char *traducir(Seg *t, int s, unsigned long off, unsigned long *fis)
{
if (s < 0 || s >= 4) return "segmento inexistente";
if (off >= t[s].limite) return "desplazamiento fuera de rango";
if (!t[s].r) return "sin permiso de lectura";
*fis = t[s].base + off;
return NULL;
}
int main(void)
{
Seg t[4] = {
{0x10000, 0x3000, 1, 0, 1}, /* código */
{0x20000, 0x2000, 1, 1, 0}, /* datos */
{0x30000, 0x1000, 1, 1, 0}, /* pila */
{0x00000, 0x0000, 0, 0, 0} /* sin usar */
};
struct { int s; unsigned long off; } casos[] = {
{0, 0x0500}, {0, 0x3000}, {1, 0x1FFF}, {2, 0x0FFF}, {3, 0x0000}, {5, 0x0000}
};
for (int i = 0; i < 6; i++) {
unsigned long f;
const char *err = traducir(t, casos[i].s, casos[i].off, &f);
if (err) printf("seg %d off 0x%04lx -> SIGSEGV (%s)\\n", casos[i].s, casos[i].off, err);
else printf("seg %d off 0x%04lx -> fisica 0x%05lx\\n", casos[i].s, casos[i].off, f);
}
return 0;
}
$ gcc -std=c17 -Wall -Wextra -o seg_sim seg_sim.c
$ ./seg_sim
seg 0 off 0x0500 -> fisica 0x10500
seg 0 off 0x3000 -> SIGSEGV (desplazamiento fuera de rango)
seg 1 off 0x1fff -> fisica 0x21fff
seg 2 off 0x0fff -> fisica 0x30fff
seg 3 off 0x0000 -> SIGSEGV (segmento inexistente)
seg 5 off 0x0000 -> SIGSEGV (segmento inexistente)
3. La tabla de segmentos editable
La tabla tiene 4 entradas. Cada una tiene base, límite y permisos (r, w, x). El usuario puede modificar cualquier campo para experimentar.
4. Traducción paso a paso
Para una dirección lógica (s, d):
- Validar el segmento: s debe estar entre 0 y 3. Si no, falla.
- Comprobar el desplazamiento: d debe ser menor que el límite. Si no, falla.
- Comprobar permisos: el modo de acceso (lectura/escritura/ejecución) debe estar permitido.
- Traducir: dirección física = base[s] + d.
5. Provocar fallas de protección
Se pueden provocar fallas de distintos tipos:
- Segmento inválido: usar un número de segmento fuera de rango (ej. 5 o -1).
- Desplazamiento fuera de rango: usar un desplazamiento ≥ límite.
- Permiso denegado: escribir en un segmento de solo lectura (r-x) o ejecutar datos (rw-).
- Segmento sin usar: el segmento 3 tiene límite 0, cualquier desplazamiento falla.
6. El simulador interactivo
Memoria de segmentos editable. Introduce una dirección lógica y observa la traducción o la falla.
Simulador · segmentación completa
| Campo | Valor |
|---|---|
| Base | |
| Límite | |
| Permisos | |
| ¿Segmento válido? | |
| ¿Dentro del límite? | |
| ¿Permiso concedido? | |
| Resultado | |
| Dirección física |
Tabla de segmentos (editable):
7. Qué observar
- Segmento inválido: cualquier número fuera de 0-3 genera falla.
- Desplazamiento fuera de rango: el límite es exclusivo.
- Permiso denegado: escribir en código (r-x) o ejecutar datos (rw-) falla.
- Segmento sin usar: límite 0, cualquier desplazamiento falla.
- Traducción correcta: física = base + desplazamiento.
8. Limitaciones del simulador
Este simulador es una simplificación. No modela:
- Los niveles de privilegio (DPL, RPL).
- La tabla de segmentos en memoria (se asume que está en registros).
- La compartición real de segmentos entre procesos.
- La paginación (que es lo que usa Linux realmente).
9. En Linux hoy
En Linux moderno, la segmentación se usa de forma plana y la protección se hace por páginas. Pero los conceptos siguen:
- ELF: los segmentos LOAD definen regiones con permisos (r, w, x).
- mprotect: cambia los permisos de una región.
- /proc/PID/maps: muestra las regiones como "segmentos" lógicos.
10. Resumen
- El simulador traduce direcciones lógicas (segmento, desplazamiento) usando una tabla editable.
- La traducción falla si el segmento es inválido, el desplazamiento supera el límite o falta permiso.
- Se pueden provocar fallas de distintos tipos modificando la tabla o la dirección.
- En Linux, la protección real se hace por páginas, pero los conceptos persisten.
11. Preguntas de repaso
Intenta responder cada una antes de abrir la respuesta.
1. ¿Qué fallas se pueden provocar en el simulador?
Segmento inválido, desplazamiento fuera de rango y permiso denegado.
2. ¿Cómo se edita la tabla de segmentos?
Cambiando los campos base, límite y permisos (r, w, x) de cada segmento.
3. ¿Qué ocurre si el límite es 0?
Cualquier desplazamiento (≥ 0) supera el límite, por lo que todo acceso falla.
4. ¿Qué diferencia hay entre una falla por rango y una por permiso?
La de rango es por desplazamiento ≥ límite; la de permiso es porque el modo de acceso no está permitido.
5. ¿Por qué el simulador no modela niveles de privilegio?
Por simplicidad: los niveles (DPL, RPL) son propios de x86 y añadirían complejidad.
6. ¿Qué significa que un segmento tenga permisos r-x?
Se puede leer y ejecutar, pero no escribir. Es típico del código.
7. ¿Cómo se relaciona este simulador con SIGSEGV?
Cada falla del simulador corresponde a una SIGSEGV en un sistema real.
8. ¿Qué herramienta de Linux muestra las regiones como segmentos?
/proc/PID/maps, que lista las regiones con sus permisos y origen.
Para practicar
- Configura el segmento 0 con base 0x10000 y límite 0x1000. Traduce (0, 0x0FFF) y (0, 0x1000). ¿Cuál falla?
- Cambia los permisos del segmento 1 a r-- (solo lectura) y evalúa (1, 0x0000, 'w'). ¿Qué falla?
- Añade un segmento 4 con base 0x40000 y límite 0x2000. Modifica el simulador para soportarlo.
- Traduce (0, 0x0500) con base 0x20000. ¿Cuál es la física?
- Explica por qué un segmento con límite 0 es útil (segmento sin usar).
- Compara el simulador con el de segmentación (tema 15): ¿qué añade este?
- Investiga cómo el ELF define los segmentos LOAD y sus permisos.