Gestión de memoria — práctica con problemas guiados paso a paso: traducir con paginación, segmentación con límites, la TLB y un ejercicio con el formato del examen (y la dirección física que di para un segmento que no existía)
En un simulacro de IC2 tenía una tabla de segmentos y tres direcciones lógicas para traducir. Las dos primeras salieron bien. La tercera era ⟨1, 400⟩, con el segmento 1 en la base 6300 y límite 400, y yo sumé sin pensar: 6300 + 400 = 6700. Al corregir, ponía «excepción». El segmento tiene 400 bytes, del desplazamiento 0 al 399, así que el 400 ya está fuera. Mi dirección física apuntaba al primer byte de otro segmento, justo lo que la MMU tiene que impedir. Desde entonces, antes de sumar nada, compruebo.
Esta es la práctica guiada de gestión de memoria. En la teoría de gestión de memoria viste la MMU, la memoria contigua, la segmentación, la paginación y la TLB, con gcc repartido por los marcos del portátil. Aquí resolvemos cuatro problemas paso a paso, como en la parte escrita y en los cálculos del test: traducir direcciones con paginación (en decimal y en hexadecimal), traducir con segmentación comprobando el límite, calcular el tiempo efectivo de acceso con TLB y un ejercicio con el formato del examen (tamaño de la tabla de páginas y los tres ajustes). Después, en los ejercicios de gestión de memoria, te toca a ti.
Tabla de Contenidos
Antes de empezar
Conviene tener claro:
- Que 1 KiB son 1024 bytes y que los tamaños de página son potencias de 2.
- Paginación: dirección lógica = ⟨página, desplazamiento⟩, con página = dirección / tamaño de página (división entera) y desplazamiento = el resto; física = marco × tamaño + desplazamiento.
- Segmentación: ⟨segmento, desplazamiento⟩; física = base + desplazamiento solo si desplazamiento < límite.
- La fórmula de la TLB: .
Si alguno te suena dudoso, repasa la teoría antes de seguir.
Con páginas que son potencia de 2, en hexadecimal no hace falta dividir: los bits bajos son el desplazamiento y los altos, la página. Con 4 KiB (), las tres últimas cifras hexadecimales son el desplazamiento.
Cómo se resuelve un problema de memoria
Los cuatro problemas siguen el mismo método de cuatro pasos:
- Pasa los tamaños a bytes (o a potencias de 2) y apunta en qué base viene cada dirección.
- Parte la dirección en sus dos campos: página y desplazamiento, o segmento y desplazamiento.
- Comprueba y traduce: en segmentación, primero el límite; en paginación, que la página exista en la tabla. Después, sustituye o suma.
- Comprueba el resultado: que la física caiga dentro del marco o del segmento correspondiente, y que el desplazamiento no haya cambiado.
Problema 1: traducir con paginación
Enunciado. a) Con páginas de 2 KiB, traduce la dirección lógica 5000 con esta tabla de páginas: página 0 → marco 3, página 1 → marco 11, página 2 → marco 7, página 3 → marco 4. b) Con páginas de 4 KiB, traduce 0x1A3C sabiendo que la página 0 está en el marco 0x2 y la página 1 en el marco 0x5.
La idea
La MMU no suma nada a la dirección lógica: la parte en dos. El desplazamiento dentro de la página pasa tal cual; solo el número de página se sustituye por el número de marco. En decimal se parte dividiendo entre el tamaño de página; en hexadecimal, si la página es , cortando las tres últimas cifras.
Paso a paso
a) 2 KiB = 2048 bytes.
La página 2 está en el marco 7:
b) 4 KiB = bytes: los 12 bits bajos (tres cifras hex) son el desplazamiento.
La página 1 está en el marco 0x5, así que la física es el marco seguido del mismo desplazamiento: 0x5A3C. Sin multiplicar: en hexadecimal, .
Comprobación
- a) El desplazamiento tiene que ser menor que el tamaño de página: 904 < 2048. Y la física cae dentro del marco 7, que va de 14336 a 16383.
- b) Las tres últimas cifras de la física son las mismas que las de la lógica (A3C): el desplazamiento no cambia.
- En decimal, 0x1A3C = 6716 = 1 · 4096 + 2620, y 0x5A3C = 23100 = 5 · 4096 + 2620: cuadra.
Preguntas que te puedes hacer
¿Por qué no se suma la base, como en la segmentación? Porque las páginas y los marcos tienen el mismo tamaño y están alineados: basta con cambiar el número de página por el de marco. Por eso la paginación es tan barata en hardware.
¿Y si la página no está en la tabla (o su bit de válida es 0)? La MMU lanza una excepción. Si hay memoria virtual, es un fallo de página y el sistema operativo la trae del disco (lo ves en el tema siguiente).
¿Cuántos bits tiene el desplazamiento con páginas de 2 KiB? 11, porque . En una dirección de 16 bits quedarían 5 para la página: 32 páginas.
¿Por qué el ejemplo de la teoría con 4 KiB daba 2604 de desplazamiento? Porque 4 KiB son 4096 bytes, no 4000. Usar potencias de 10 en lugar de potencias de 2 es el error más caro de este tema.
Tomar 2 KiB como 2000 bytes. Con 5000 saldría página 2 y desplazamiento 1000, y una física de 7 · 2000 + 1000 = 15000: dos números mal.
Pruébalo tú
- Traduce la dirección lógica 2047 y la 2048 del apartado a). ¿Por qué caen en marcos tan distintos si solo se diferencian en 1?
- Con páginas de 4 KiB, ¿qué página y qué desplazamiento tiene 0x3FFF?
Problema 2: segmentación con límites
Enunciado. La tabla de segmentos de un proceso es:
| Segmento | Base | Límite |
|---|---|---|
| 0 (código) | 1400 | 1000 |
| 1 (pila) | 6300 | 400 |
| 2 (datos) | 4300 | 1100 |
Traduce las direcciones lógicas ⟨0, 430⟩, ⟨1, 400⟩ y ⟨2, 1099⟩.
La idea
Cada segmento tiene su tamaño (el límite), así que el desplazamiento válido va de 0 a límite − 1. La MMU hace siempre lo mismo y en este orden: comprueba que el desplazamiento es menor que el límite y, solo si lo es, suma la base. Si no, excepción y el proceso no accede a nada.
Paso a paso
| Dirección | ¿Desplazamiento < límite? | Física |
|---|---|---|
| ⟨0, 430⟩ | 430 < 1000: sí | 1400 + 430 = 1830 |
| ⟨1, 400⟩ | 400 < 400: no | excepción |
| ⟨2, 1099⟩ | 1099 < 1100: sí | 4300 + 1099 = 5399 |
Comprobación
- 1830 está entre 1400 y 2399 (el segmento 0). 5399 está entre 4300 y 5399: es justo el último byte del segmento 2.
- ⟨1, 400⟩ daría 6700, que ya no es del segmento 1 (que acaba en 6699).
Preguntas que te puedes hacer
¿Por qué 1099 vale y 400 no, si los dos son «el tamaño menos algo»? Porque el límite del segmento 2 es 1100 (1099 es el último válido) y el del segmento 1 es 400 (el último válido es 399). La comparación es siempre estricta: menor que el límite.
¿Qué pasaría si la MMU sumara primero y comprobara después? Daría el mismo resultado en las direcciones válidas, pero comprobar sobre la física es más difícil (habría que conocer el final de cada segmento en memoria). Comprobar el desplazamiento contra el límite es una sola comparación.
¿Los segmentos pueden estar en cualquier orden en la RAM? Sí: el 0 en 1400, el 2 en 4300 y el 1 en 6300. Cada uno es un bloque contiguo, pero el proceso no necesita estar entero junto. Por eso la segmentación sufre fragmentación externa.
¿Y si el segmento no existe (⟨3, 10⟩)? El número de segmento se compara con el tamaño de la tabla: si es mayor, también hay excepción.
Sumar la base sin comprobar el límite, o comprobar con «≤». En el examen, una dirección inválida con su física calculada está mal aunque la suma esté bien.
Pruébalo tú
- Traduce ⟨0, 999⟩, ⟨0, 1000⟩ y ⟨2, 0⟩.
- ¿Qué límite mínimo tendría que tener el segmento 1 para que ⟨1, 400⟩ fuera válida?
Problema 3: la TLB y el tiempo efectivo de acceso
Enunciado. Un sistema paginado tiene una TLB de 5 ns y una memoria de 80 ns. a) Calcula el tiempo efectivo de acceso con una tasa de aciertos del 90 % y del 98 %. b) ¿Cuánto tardaría sin TLB? c) ¿Y con una tabla de dos niveles y el 90 % de aciertos?
La idea
Cada acceso pasa siempre por la TLB. Si acierta, ya tenemos el marco y solo falta leer el dato: un acceso a memoria. Si falla, hay que leer la entrada de la tabla de páginas en memoria y después el dato: dos accesos (con una tabla de dos niveles, tres). El tiempo efectivo es la media ponderada.
Paso a paso
a) Con acierto: ns. Con fallo: ns.
b) Sin TLB, cada acceso son dos accesos a memoria: ns. La TLB al 90 % lo deja en 93: casi la mitad.
c) Con dos niveles, un fallo de TLB cuesta tres accesos (dos entradas de tabla y el dato): ns.
Comprobación
- El resultado tiene que estar entre el caso de acierto (85) y el de fallo (165): 93 y 86,6 lo están.
- Al subir la tasa de aciertos, el tiempo baja hacia 85: con el 100 % sería 85 exactos.
- Con dos niveles solo cambia el coste del fallo; el acierto sigue costando 85.
Preguntas que te puedes hacer
¿Por qué se suma la TLB también en el fallo? Porque la TLB se consulta siempre primero: solo después de fallar se va a la tabla. Hay diseños que consultan en paralelo, pero en el tema (y en el examen) se suma.
¿Por qué la TLB funciona con tan pocas entradas? Por la localidad: en un intervalo corto, el programa usa pocas páginas, y la TLB guarda justo esas.
¿Qué pesa más, mejorar la TLB de 5 a 2 ns o subir los aciertos del 90 al 98 %? Con 2 ns y el 90 %: ns. Subir aciertos da 86,6: en este sistema compensa más acertar que ser rápido.
¿Esto es lo mismo que el tiempo efectivo con fallos de página? Es la misma idea de media ponderada, pero con números muy distintos: un fallo de página cuesta milisegundos. Lo ves en el tema siguiente.
Poner en el fallo de TLB un solo acceso a memoria (olvidando la tabla) o no sumar la TLB en el acierto. Escribe siempre los dos caminos antes de ponderar.
Pruébalo tú
- ¿Qué tasa de aciertos hace falta para que el tiempo efectivo sea 90 ns con la TLB de 5 ns?
- Repite el apartado c) con una tabla de tres niveles.
Problema 4: un ejercicio con el formato del examen
En la parte escrita y en los cálculos del test de IC2 aparecen el tamaño de la tabla de páginas y la asignación de memoria contigua con primer, mejor y peor ajuste. Se valora que se vean las cuentas y el estado de los huecos después de cada asignación. Este ejercicio es original y está escrito con ese formato.
Ejercicio. a) Un sistema tiene direcciones lógicas de 32 bits, páginas de 8 KiB y entradas de tabla de 4 bytes. ¿Cuántas entradas tiene la tabla de páginas de un proceso y cuánto ocupa? b) La memoria tiene huecos de 150, 400, 220, 500 y 120 KiB, en ese orden. Llegan, por este orden, los procesos A (180 KiB), B (350 KiB), C (90 KiB) y D (420 KiB). Indica en qué hueco va cada uno con primer ajuste, mejor ajuste y peor ajuste.
| Proceso | Primer ajuste | Mejor ajuste | Peor ajuste |
|---|---|---|---|
| A (180) | ___ | ___ | ___ |
| B (350) | ___ | ___ | ___ |
| C (90) | ___ | ___ | ___ |
| D (420) | ___ | ___ | ___ |
La idea
a) El desplazamiento ocupa los bits que hacen falta para recorrer una página y el resto son bits de página: cada combinación es una entrada. b) Para cada proceso, por orden, se mira la lista de huecos tal como ha quedado después del anterior: primer ajuste coge el primero que cabe, mejor ajuste el más pequeño que cabe y peor ajuste el más grande.
Paso a paso
a) 8 KiB = bytes: 13 bits de desplazamiento, así que quedan bits de página.
b) Huecos iniciales: 150, 400, 220, 500 y 120.
Primer ajuste: A (180) no cabe en 150; va al 400 (quedan 220). B (350): 150 no, 220 no, 220 no, 500 (quedan 150). C (90): cabe en el primero, 150 (quedan 60). D (420): ningún hueco llega a 420 (60, 220, 220, 150, 120): espera.
Mejor ajuste: A (180): los que caben son 400, 220 y 500; el más pequeño, 220 (quedan 40). B (350): 400 y 500; el 400 (quedan 50). C (90): caben 150, 500 y 120; el 120 (quedan 30). D (420): el 500 (quedan 80).
Peor ajuste: A (180): el más grande, 500 (quedan 320). B (350): el 400 (quedan 50). C (90): el más grande ahora es el de 320, que era el 500 (quedan 230). D (420): ningún hueco llega (150, 50, 220, 230, 120): espera.
| Proceso | Primer ajuste | Mejor ajuste | Peor ajuste |
|---|---|---|---|
| A (180) | 400 | 220 | 500 |
| B (350) | 500 | 400 | 400 |
| C (90) | 150 | 120 | 500 |
| D (420) | espera | 500 | espera |
Comprobación y cómo se corrige
- a) Comprueba con la otra cuenta: bytes de espacio lógico entre por página da páginas.
- b) Después de cada asignación, escribe la lista de huecos completa. Si un hueco se usa dos veces (como el de 500 en el peor ajuste), tiene que tener sitio para los dos: 500 − 180 = 320 ≥ 90.
Se valora que se vean los bits de cada campo en a) y el estado de los huecos tras cada proceso en b). Aquí, curiosamente, el mejor ajuste es el único que coloca a los cuatro: el primer y el peor ajuste rompen el hueco grande demasiado pronto.
Decidir cada proceso con la lista de huecos inicial en lugar de con la que dejó el anterior. Con el peor ajuste, C iría al 500 «original» y no al hueco de 320 que quedó.
Pruébalo tú
- Repite el apartado a) con páginas de 4 KiB y entradas de 8 bytes.
- Con primer ajuste, ¿en qué orden tendrían que llegar los procesos para que entraran los cuatro?
Errores típicos en esta práctica
- Usar potencias de 10: 1 KiB son 1024 bytes, no 1000.
- Sumar en la paginación: la página se sustituye por el marco; el desplazamiento no cambia.
- No comprobar el límite del segmento, o comprobar con «≤».
- Olvidar la TLB en el camino del fallo, o el acceso a la tabla.
- Usar la lista de huecos inicial en todos los procesos en lugar de la que va quedando.
- No comprobar que la física cae dentro de su marco o de su segmento.
Compruébalo con Python
Este programa hace las cuentas de los cuatro problemas. La función pagina() es la división de la MMU, y ajuste() va gastando los huecos para cada proceso con las tres reglas.
# Gestión de memoria de papel: paginación, segmentación, TLB, tamaño de la tabla y ajustes.
KiB = 1024
def pagina(dl, tam, tabla):
p, d = divmod(dl, tam) # página = cociente, desplazamiento = resto
return p, d, tabla[p] * tam + d
print("paginación 2 KiB, 5000:", pagina(5000, 2 * KiB, {0: 3, 1: 11, 2: 7, 3: 4}))
p, d, f = pagina(0x1A3C, 4 * KiB, {0: 0x2, 1: 0x5})
print(f"paginación 4 KiB, 0x1A3C: página {p}, desplazamiento {d:#05x}, física {f:#06x}")
segs = {0: (1400, 1000), 1: (6300, 400), 2: (4300, 1100)} # segmento: (base, límite)
for s, d in ((0, 430), (1, 400), (2, 1099)):
base, lim = segs[s]
print(f"segmento ⟨{s}, {d}⟩:", base + d if d < lim else "excepción (desplazamiento >= límite)")
T, M = 5, 80 # ns de la TLB y de la RAM
for h in (0.9, 0.98):
print(f"TLB h={h}: {h * (T + M) + (1 - h) * (T + 2 * M):.1f} ns")
print(f"sin TLB: {2 * M} ns; dos niveles, h=0.9: {0.9 * (T + M) + 0.1 * (T + 3 * M):.1f} ns")
bits, pag, ent = 32, 8 * KiB, 4
n = 2 ** (bits - pag.bit_length() + 1) # entradas = 2^(bits de dirección - bits de desplazamiento)
print(f"tabla: 2^{bits - pag.bit_length() + 1} = {n} entradas x {ent} B = {n * ent // (1024 * 1024)} MiB")
def ajuste(huecos, procs, regla):
h, out = list(huecos), []
for nom, t in procs:
ok = [i for i, x in enumerate(h) if x >= t]
if not ok: out.append(f"{nom}: espera"); continue
i = {"primer": ok[0], "mejor": min(ok, key=lambda i: h[i]), "peor": max(ok, key=lambda i: h[i])}[regla]
out.append(f"{nom}->{huecos[i]}"); h[i] -= t
return out, h
for regla in ("primer", "mejor", "peor"):
print(regla, *ajuste([150, 400, 220, 500, 120], [("A", 180), ("B", 350), ("C", 90), ("D", 420)], regla))
Salida (ejecutado una vez):
paginación 2 KiB, 5000: (2, 904, 15240) paginación 4 KiB, 0x1A3C: página 1, desplazamiento 0xa3c, física 0x5a3c segmento ⟨0, 430⟩: 1830 segmento ⟨1, 400⟩: excepción (desplazamiento >= límite) segmento ⟨2, 1099⟩: 5399 TLB h=0.9: 93.0 ns TLB h=0.98: 86.6 ns sin TLB: 160 ns; dos niveles, h=0.9: 101.0 ns tabla: 2^19 = 524288 entradas x 4 B = 2 MiB primer ['A->400', 'B->500', 'C->150', 'D: espera'] [60, 220, 220, 150, 120] mejor ['A->220', 'B->400', 'C->120', 'D->500'] [150, 50, 40, 80, 30] peor ['A->500', 'B->400', 'C->500', 'D: espera'] [150, 50, 220, 230, 120]
Cosas que observar:
divmod(dl, tam)da a la vez la página (cociente) y el desplazamiento (resto): es todo lo que hace la MMU antes de mirar la tabla.- En el apartado b) del Problema 1, Python escribe los números en hexadecimal con
:#05xy:#06x: el desplazamiento 0xa3c aparece igual en la lógica y en la física. - La segunda dirección de segmentación sale como excepción porque la condición es
d < lim, estricta. - En
ajuste(), la listahva restando lo asignado; al final se imprime cómo quedan los huecos con cada regla.
Si quieres ver la memoria virtual de este mismo proceso, tienes el siguiente tema: memoria virtual y reemplazo de páginas.
Resumen
- Paginación: dividir entre el tamaño de página, cambiar la página por el marco, dejar el desplazamiento.
- En hexadecimal y con páginas de , las tres últimas cifras son el desplazamiento.
- Segmentación: comprobar desplazamiento < límite y, solo entonces, sumar la base.
- TLB: ; con más niveles, más accesos en el fallo.
- Tabla de páginas: entradas por el tamaño de cada una.
- Ajustes: cada proceso con los huecos que quedaron; el mejor ajuste no siempre deja más sitio, pero aquí coloca a todos.
Checklist: ¿lo has practicado?
- ¿Has hecho los cuatro problemas en papel antes de leer el paso a paso?
- ¿Sabes partir una dirección en decimal y en hexadecimal?
- ¿Compruebas el límite antes de sumar la base?
- ¿Puedes escribir los dos caminos de la TLB y ponderarlos?
- ¿Has comprobado los problemas con el programa de Python?
- ¿Has intentado los «Pruébalo tú» sin mirar la teoría?
Si has respondido que sí a casi todo, estás listo para los ejercicios de gestión de memoria, con un test de todo el tema y cálculos con casillas que se corrigen solas. ¡Nos vemos allí!
Siguiente paso: ejerciciosGestión de memoria — ejercicios tipo examen con direcciones que traducir, una TLB que acierta y huecos que no alcanzan (y el medio nanosegundo que perdí por no sumar la TLB)¿Te ha servido este artículo? Así puedes apoyar SergioLearns →



