← Planificación de la CPU Bloque 9 · Planificación en tiempo real · Tema 34 de 44

Tema 34

Simulador de tiempo real

En el tema anterior viste RM y EDF. Este tema reúne todo en un simulador interactivo que verifica si un conjunto de tareas periódicas cumple sus plazos con ambos algoritmos. El simulador muestra el Gantt, las métricas de planificabilidad (utilización, límites) y si cada tarea cumple su plazo. También permite experimentar con los parámetros para ver cuándo un conjunto deja de ser planificable.

1. Por qué un simulador de tiempo real

Los sistemas de tiempo real requieren garantías formales. Un simulador permite verificar si un conjunto de tareas cumple sus plazos antes de implementarlo en un sistema real. También permite experimentar con los parámetros para entender los límites de cada algoritmo.

Este simulador es el último del bloque 9 y cierra el estudio de la planificación en tiempo real. A partir del bloque 10, se baja a Linux.

2. Arquitectura

El simulador tiene las mismas partes que los anteriores, con dos algoritmos de tiempo real:

ParteResponsabilidadFunciones
ModeloRepresentar una tarea periódica.crearTarea
GeneradorProducir conjuntos de tareas reproducibles.generarTareas
RMSimular Rate Monotonic.simularRM
EDFSimular Earliest Deadline First.simularEDF
PlanificabilidadCalcular utilización y límites.planificabilidad
VistaDibujar Gantt y tabla.dibujarGantt, renderTabla
ControladorLeer controles, ejecutar, actualizar.dibujar

3. Simulación de RM

RM asigna prioridades estáticas por período. La simulación ejecuta las tareas por unidades de tiempo, eligiendo en cada instante la tarea lista con el período más corto:

simularRM.js
function simularRM(tareas, horizonte) {
    var restante = tareas.map(function (t) { return t.ejecucion; });
    var proximaLlegada = tareas.map(function (t) { return 0; });
    var plazo = tareas.map(function (t) { return t.periodo; });
    var bloques = [];
    var t = 0;
    var orden = tareas.map(function (t, i) { return i; }).sort(function (a, b) {
        return tareas[a].periodo - tareas[b].periodo;
    });
    while (t < horizonte) {
        var elegida = -1;
        for (var i = 0; i < orden.length; i++) {
            var ti = orden[i];
            if (restante[ti] > 0 && t >= proximaLlegada[ti] && t < plazo[ti]) {
                elegida = ti;
                break;
            }
        }
        if (elegida === -1) {
            t++;
            for (var i = 0; i < tareas.length; i++) {
                if (restante[i] <= 0 && t >= proximaLlegada[i] + tareas[i].periodo) {
                    proximaLlegada[i] += tareas[i].periodo;
                    plazo[i] = proximaLlegada[i] + tareas[i].periodo;
                    restante[i] = tareas[i].ejecucion;
                }
            }
            continue;
        }
        bloques.push({ pid: tareas[elegida].id, inicio: t, fin: t + 1 });
        restante[elegida]--;
        t++;
        for (var i = 0; i < tareas.length; i++) {
            if (restante[i] <= 0 && t >= proximaLlegada[i] + tareas[i].periodo) {
                proximaLlegada[i] += tareas[i].periodo;
                plazo[i] = proximaLlegada[i] + tareas[i].periodo;
                restante[i] = tareas[i].ejecucion;
            }
        }
    }
    return bloques;
}

4. Simulación de EDF

EDF asigna prioridades dinámicas por plazo. La simulación es similar a RM, pero en cada instante se elige la tarea con el plazo más cercano:

simularEDF.js
function simularEDF(tareas, horizonte) {
    var restante = tareas.map(function (t) { return t.ejecucion; });
    var proximaLlegada = tareas.map(function (t) { return 0; });
    var plazo = tareas.map(function (t) { return t.periodo; });
    var bloques = [];
    var t = 0;
    while (t < horizonte) {
        var elegida = -1;
        var minPlazo = Infinity;
        for (var i = 0; i < tareas.length; i++) {
            if (restante[i] > 0 && t >= proximaLlegada[i] && t < plazo[i]) {
                if (plazo[i] < minPlazo) { minPlazo = plazo[i]; elegida = i; }
            }
        }
        if (elegida === -1) {
            t++;
            for (var i = 0; i < tareas.length; i++) {
                if (restante[i] <= 0 && t >= proximaLlegada[i] + tareas[i].periodo) {
                    proximaLlegada[i] += tareas[i].periodo;
                    plazo[i] = proximaLlegada[i] + tareas[i].periodo;
                    restante[i] = tareas[i].ejecucion;
                }
            }
            continue;
        }
        bloques.push({ pid: tareas[elegida].id, inicio: t, fin: t + 1 });
        restante[elegida]--;
        t++;
        for (var i = 0; i < tareas.length; i++) {
            if (restante[i] <= 0 && t >= proximaLlegada[i] + tareas[i].periodo) {
                proximaLlegada[i] += tareas[i].periodo;
                plazo[i] = proximaLlegada[i] + tareas[i].periodo;
                restante[i] = tareas[i].ejecucion;
            }
        }
    }
    return bloques;
}

5. Planificabilidad

El simulador calcula la planificabilidad de ambos algoritmos:

Además, verifica si cada tarea cumple su plazo en la simulación: si en algún período la tarea no termina antes del plazo, se marca como «no cumple».

6. Gantt de ambas

El simulador muestra el Gantt de RM y de EDF uno encima del otro, para comparar cómo se ejecutan las tareas en cada algoritmo. Los bloques se comprimen (instancias consecutivas del mismo pid se fusionan) para que el Gantt sea legible.

7. Tabla de resultados

La tabla muestra, para cada tarea, su período, ejecución, utilización y si cumple el plazo con RM y con EDF:

renderTabla.js
function renderTabla(tareas, cumpleRM, cumpleEDF, filasEl, promEl) {
    filasEl.innerHTML = '';
    var U = 0;
    tareas.forEach(function (t, i) {
        var tr = document.createElement('tr');
        [ 'τ' + t.id, t.periodo, t.ejecucion,
          (t.ejecucion / t.periodo).toFixed(3),
          cumpleRM[i] ? 'Sí' : 'No',
          cumpleEDF[i] ? 'Sí' : 'No' ].forEach(function (v) {
            var td = document.createElement('td');
            td.textContent = v;
            tr.appendChild(td);
        });
        filasEl.appendChild(tr);
        U += t.ejecucion / t.periodo;
    });
    var n = tareas.length;
    var limiteRM = n * (Math.pow(2, 1 / n) - 1);
    promEl.textContent = 'U = ' + U.toFixed(3) +
        ' | Límite RM = ' + limiteRM.toFixed(3) +
        ' | Límite EDF = 1,000';
}

8. Los controles

Los controles permiten ajustar el conjunto de tareas:

9. Simulador interactivo

Este simulador verifica si un conjunto de tareas cumple sus plazos con RM y con EDF. Cambia los parámetros y observa:

Simulador · tiempo real (RM y EDF)

Rate Monotonic

EDF

TareaPeríodoEjecuciónUtilizaciónRM cumple?EDF cumple?

10. Verificación y casos de prueba

CasoEntradaResultado esperado
Baja utilización2 tareas, períodos 10, rafagas 2,2U = 0,4. Planificable por RM y EDF.
Alta utilización3 tareas, períodos 5,10,15, rafagas 2,3,4U = 0,97. Planificable por EDF, no garantizado por RM.
Sobrecarga2 tareas, períodos 5,5, rafagas 3,3U = 1,2. No planificable por ninguno.
Un proceso1 tarea, período 10, rafaga 5U = 0,5. Planificable por ambos.

11. Resumen

12. Preguntas de repaso

Intenta responder cada una antes de abrir la respuesta.

1. ¿Qué verifica el simulador?

Si un conjunto de tareas periódicas cumple sus plazos con RM y con EDF.

2. ¿Qué muestra el Gantt?

La ejecución de las tareas en el tiempo, con RM y con EDF.

3. ¿Qué calcula la planificabilidad?

La utilización total y los límites de RM y EDF.

4. ¿Qué ocurre si U > 1?

No es planificable por ningún algoritmo.

5. ¿Qué ocurre si U ≤ límite RM?

Planificable por RM y por EDF.

6. ¿Qué ocurre si límite RM < U ≤ 1?

Planificable por EDF, no garantizado por RM.

7. ¿Cómo se comprime el Gantt?

Fusionando instancias consecutivas del mismo pid.

8. ¿Qué parámetros ajusta el simulador?

Número de tareas, período base, ráfaga base y semilla.

9. ¿Qué bloque del curso cierra este simulador?

El bloque 9 (planificación en tiempo real).

10. ¿Qué algoritmo admite más carga?

EDF (hasta U = 1,000).

Para practicar

  1. Ejecuta el simulador con U < 0,7 y verifica que ambos cumplen.
  2. Aumenta la ráfaga hasta que U > 1 y observa el fallo.
  3. Encuentra un caso donde RM falla pero EDF cumple.
  4. Modifica el simulador para mostrar el número de plazos incumplidos.
  5. Implementa la planificabilidad exacta (verificación por simulación, no solo por utilización).
  6. Investiga cómo SCHED_DEADLINE de Linux verifica la planificabilidad.