Repaso final: chuleta, flashcards y simulacro del LC3
Chuleta
Sección titulada «Chuleta»Memoria virtual
Sección titulada «Memoria virtual»- Partes de una dirección: offset = ; VPN = bits virtuales − offset; PFN = bits físicos − offset.
- Tabla: entradas = (o memoria virtual / página); tamaño = entradas × bytes por PTE.
- Multinivel con tablas de una página: bits por nivel = ; niveles = ⌈VPN / bits por nivel⌉.
- Accesos por referencia: sin TLB, k niveles + 1. Con TLB: 1 si acierta, k + 1 si falla.
- Tiempo efectivo de acceso: si siempre se consulta la TLB. Despejar h: .
- PTE: P/V (presente), M (dirty), R/U (uso), protección, frame. Invertida: una entrada por frame, con hash de (página, PID).
- Page fault: trap → validar → frame libre o víctima (escribirla si M = 1) → leer del disco (el proceso se bloquea) → actualizar la PTE → reiniciar la instrucción.
- Reemplazo:
- OPT: la que se usa más tarde;
- LRU: la usada hace más tiempo;
- FIFO: la más vieja en memoria;
- Clock: pone u = 0 al pasar y saca la primera con u = 0;
- Clock mejorado: prefiere (u, m) = (0, 0) > (0, 1) > (1, 0) > (1, 1).
- Belady: FIFO y Clock pueden tener más fallos con más frames; LRU y OPT (algoritmos de pila) no.
- Conjunto residente:
- fija + local, variable + local o variable + global; fija + global es imposible;
- working set = las páginas de las últimas Δ referencias;
- PFF: crecer si los fallos están muy seguidos, encogerse si no.
- Limpieza: por demanda (2 E/S) vs precleaning (E/S desperdiciada) → page buffering.
- Thrashing: la CPU cae y el disco se satura. Hay que bajar el nivel de multiprogramación (criterio L = S o 50 %).
- UNIX/Linux: reloj de dos manecillas (scanrate, handspread), lazy buddy, COW; en Linux, split LRU (activa/inactiva, kswapd), buddy de frames y slab/SLUB/SLOB.
Deadlock y sincronización
Sección titulada «Deadlock y sincronización»- Coffman: exclusión mutua + hold and wait + no expropiación + espera circular.
- Filósofos:
- semáforo central (1) → sin deadlock, come uno a la vez;
- k ≤ N − 1 sillas → sin deadlock;
- asimétrica → sin deadlock, con paralelismo ⌊N/2⌋;
- Tanenbaum → sin deadlock, pero puede haber starvation (tanen-5-1, tanen-4-2).
- trylock: rompe hold and wait, pero puede haber livelock. La solución robusta es el orden global de los locks.
- Barbero:
sem_trywait(seats)(no bloquea);barber_chair,client_seatyhair_cut(el barbero decide cuándo termina);- con N barberos, un panel (
write_panel= 1,read_panel= 0), ybarber_chairsobra.
- Valgrind:
Invalid write/read(fuera del bloque o ya liberado),Invalid free(doble o no-heap),definitely lost(fuga),Conditional jump … uninitialised(en el if, no en la declaración);- no ve desbordes del stack;
- helgrind encuentra races aunque el resultado haya salido bien.
Flashcards
Sección titulada «Flashcards»Flashcards
dominadas 0/40Simulacro del LC3
Sección titulada «Simulacro del LC3»¿Quieres algo más duro? Pasa después a LC3 · peor escenario. Para las 4 teóricas (las del libro), repasa antes Stallings para el LC3.
Código 1 (3 pts) · Barbero con sem_trywait
Sección titulada «Código 1 (3 pts) · Barbero con sem_trywait»Completa los huecos para 1 barbero y 5 sillas de espera. Un cliente que no encuentra silla se va sin bloquearse, el barbero duerme si no hay clientes, y el cliente no se levanta hasta que el barbero termina.
sem_t seats, barber_chair, client_seat, hair_cut;
void *cliente(void *a) { void *barbero(void *a) { if (/* [1] */) { while (1) { /* [2] */; /* [5] */; sem_post(&seats); cut_shave(); /* [3] */; /* [6] */; /* [4] */; } sem_post(&barber_chair); } } else leaves();}/* main: sem_init(&seats,0,[7]); sem_init(&barber_chair,0,[8]); sem_init(&client_seat,0,[9]); sem_init(&hair_cut,0,[10]); */Solución y pauta (probada en una ejecución de prueba)
| Hueco | Código |
|---|---|
| [1] | sem_trywait(&seats) == 0 |
| [2] | sem_wait(&barber_chair) |
| [3] | sem_post(&client_seat) |
| [4] | sem_wait(&hair_cut) |
| [5] | sem_wait(&client_seat) |
| [6] | sem_post(&hair_cut) |
| [7]–[10] | 5, 1, 0, 0 |
Es la solución de la diap. 41, probada con 300 clientes: 237 atendidos y 63 que se fueron, nunca más de 5 esperando (barbero).
Pauta: 0.3 por hueco. [1] con sem_wait en lugar de sem_trywait vale 0, porque el cliente se bloquearía en vez de irse.
Código 2 (3 pts) · Errores de memoria
Sección titulada «Código 2 (3 pts) · Errores de memoria» 4 char *duplicar(const char *s) { 5 char *d = malloc(strlen(s)); 6 strcpy(d, s); 7 return d; 8 } 910 int main(void) {11 int *v = malloc(5 * sizeof(int));1213 for (int i = 0; i <= 5; i++)14 v[i] = i * i;15 char *nombre = duplicar("utec");16 printf("%s %d\n", nombre, v[2]);17 free(v);18 printf("%d\n", v[0]);19 return 0;20 }Indica cada error que reportaría memcheck (tipo y línea) y corrige el programa.
Solución (salida real de memcheck)
Invalid write of size 4 at main (lc3_mem.c:14) 0 bytes after a block of size 20 alloc'dInvalid write of size 1 (strcpy, línea 6) 0 bytes after a block of size 4 alloc'dInvalid read of size 1 (printf, línea 16) 0 bytes after a block of size 4 alloc'dInvalid read of size 4 at main (lc3_mem.c:18) 0 bytes inside a block of size 20 free'd4 bytes in 1 blocks are definitely lostERROR SUMMARY: 5 errors from 5 contexts| # | Línea | Error | Corrección |
|---|---|---|---|
| 1 | 14 | i <= 5 escribe v[5], fuera de un bloque de 5 enteros | i < 5 |
| 2 | 6 (por la 5) | malloc(strlen(s)) no deja espacio para el '\0': strcpy escribe 1 byte de más | malloc(strlen(s) + 1) |
| 3 | 16 | printf("%s") lee ese mismo byte fuera del bloque (consecuencia del error 2) | se arregla con el error 2 |
| 4 | 18 | lee v[0] después del free(v) (uso tras liberar) | mover free(v) al final |
| 5 | — | nombre nunca se libera: 4 bytes definitely lost | free(nombre) antes de return |
La versión corregida da 0 errores. Ojo: el programa original imprimió bien (utec 4, 0). Por eso hay que usar Valgrind: los bugs de memoria muchas veces no se notan.
Pauta: 0.5 por error bien ubicado y 0.5 por un programa corregido que compile.
Quiz: teóricas (5 pts) y análisis (9 pts)
Sección titulada «Quiz: teóricas (5 pts) y análisis (9 pts)»Teóricas (1.25 c/u)
0/4 correctas · 0 respondidasAnálisis (3 c/u)
0/3 correctas · 0 respondidasDespués del simulacro: corrige como tutor
Sección titulada «Después del simulacro: corrige como tutor»Un simulacro sirve el doble si diagnosticas cada error en vez de solo contarlo. Por cada pregunta que perdiste puntos:
- Busca el primer paso que hiciste mal, no solo la respuesta final.
- Clasifícalo y haz lo que dice la tabla:
| Tipo de error | Señal | Qué hacer |
|---|---|---|
| Conceptual | no sabías la regla, o tenías una idea equivocada («inseguro = deadlock») | vuelve a la página del tema: «En simple», «Predice» y «Errores que cuestan puntos» |
| Procedimental | sabías la regla, pero te saltaste o desordenaste un paso (olvidaste el bit de validez) | rehaz los peldaños 2 y 3 de la escalera de ese tema |
| De cálculo | potencias de 2, binario o hexadecimal, sumas | un ejercicio corto solo de esa operación, y vuelve al problema |
| De interpretación | leíste mal el enunciado o no declaraste la convención | vuelve a leer el enunciado y subraya los supuestos (marcos, convención de Clock, niveles) |
- Marca tu nivel en esa página (📈) para que el panel de repaso te la vuelva a mostrar en el momento justo.
- Escribe tu hoja de errores: 5 a 8 líneas con lo que no puedes volver a hacer. Léela la mañana del LC3.
Fuente ·Todo el material de sem_9 y las páginas de esta sección · Simulacro propio; respuestas verificadas con el simulador de reemplazo, un recorrido exhaustivo de estados y ejecuciones de prueba (barber.c, lc3_mem.c)