Académique Documents
Professionnel Documents
Culture Documents
Parte 3
Septiembre de 2007
Unidad 3
Planificación
El planificador es un módulo del sistema operativo que asigna tiempo de CPU a los
procesos activos
Linux utiliza un algoritmo de planificación que tiene como objetivo una distribución
equitativa del tiempo de CPU entre los procesos activos en el sistema
Un proceso se bloquea
Expulsivos.- las tareas pueden ser expulsadas del procesador antes de concluir
su ejecución
No expulsivo
Se calcula el plan de ejecución off-line
Mejora el tiempo de respuesta
promedio con respecto al anterior
a) First-Come First-Served b) Shortes Job First
Expulsivo
En cada instante de planificación se elige a la tarea a la que quede el menor
tiempo de ejecución
Cuando alguna tarea se activa, se compara su tiempo de ejecución con el
tiempo de ejecución restante de la tarea actual, y si es menor el tiempo de
ejecución de la nueva tarea la actual es expulsada del procesador
Este esquema permite que las tareas pequeñas tengan un mejor tiempo de
respuesta
planificador de CPU
¿Cuáles tareas deben
pasar de disco a memoria
planificador de Memoria principal?
Round-Robin
Expulsivo
Expulsivo
Expulsivo
Expulsivo
Expulsivo
El algoritmo garantiza la
asignación equitativa del tiempo
de procesador entre los usuarios
las tareas de tiempo-real tienen un tiempo límite para concluir su ejecución (plazo o
deadline)
ϕi.- fase
pi.- periodo
Rate Monotonic
Expulsivo
Estático (el valor de prioridad de las tareas no cambia durante la ejecución del
sistema)
Expulsivo
En Linux,
Linux la prioridad de los procesos se asigna de manera dinámica, lo que
significa que su valor cambia en el tiempo
Por otra parte, la duración del quantum de ejecución es crítica para el desempeño
del sistema. Linux asigna una prioridad fija a cada proceso y calcula el valor del
quantum de la siguiente manera:
Por otra parte, Se ha comentado que los procesos son planificados en base a
una prioridad dinámica, cuyo valor varía desde 100 (mas alta prioridad)
hasta 139 (mas baja prioridad)
El valor de bono varía entre 0 y 10. Su valor final depende del average sleep
time (tiempo promedio de inactividad) del proceso
need_resched:
preempt_disable();
prev = current;
release_kernel_lock( prev );
need_resched_nonpreemptible:
rq = this_rq();
now = sched_clock();
if ( likely (( long long )( now – prev->timestamp ) < NS_MAX_SLEEP_AVG)) {
run_time = now - prev->timestamp;
if ( unlikely (( long long )( now – prev->timestamp ) < 0))
run_time = 0;
} else
run_time = NS_MAX_SLEEP_AVG;
run_time /= ( CURRENT_BONUS( prev ) ? : 1 );
switch_count = &prev->nivcsw;
if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
switch_count = &prev->nvcsw;
unlikely(signal_pending(prev))))
prev->state = TASK_RUNNING;
else {
if (prev->state == TASK_UNINTERRUPTIBLE)
rq->nr_uninterruptible++;
deactivate_task(prev, rq);
cpu = smp_processor_id();
if ( unlikely ( ! rq->nr_running ) ) {
go_idle:
idle_balance(cpu, rq);
if ( ! rq->nr_running ) {
next = rq->idle;
rq->expired_timestamp = 0;
wake_sleeping_dependent(cpu, rq);
if ( ! rq->nr_running )
goto switch_tasks;
}
} else {
if ( dependent_sleeper(cpu, rq)) {
next = rq->idle;
goto switch_tasks;
}
if ( unlikely ( ! rq->nr_running ) )
goto go_idle;
}
switch_tasks:
sched_info_switch( prev, next );
if ( next == rq->idle)
if ( likely( prev != next)) {
schedstat_inc(rq, sched_goidle);
next->timestamp = now;
prefetch(next);
rq->nr_switches++;
prefetch_stack(next);
rq->curr = next;
clear_tsk_need_resched(prev);
++*switch_count;
rcu_qsctr_inc(task_cpu(prev));
prepare_task_switch( rq, next );
prev = context_switch( rq,
update_cpu_clock(prev, rq, now); prev, next);
barrier();
prev->sleep_avg -= run_time;
if ((long) prev->sleep_avg <= 0) finish_task_switch(this_rq(), prev);
prev->sleep_avg = 0; } else
prev->timestamp = prev->last_ran = now; spin_unlock_irq( &rq->lock );
Al conjunto de datos que deben ser cargados en los registros del procesador
antes de que el proceso reanude su ejecución se le llama contexto de hardware
Al conjunto de datos que deben ser cargados en los registros del procesador
antes de que el proceso reanude su ejecución se le llama contexto de hardware
Las versiones anteriores de Linux hacen uso del soporte que ofrecen
algunos procesadores para llevar a cabo el cambio de contexto
static inline
task_t * context_switch( runqueue_t *rq, task_t *prev, task_t *next)
{
struct mm_struct *mm = next->mm;
struct mm_struct *oldmm = prev->active_mm;
if ( unlikely ( ! mm )) {
next->active_mm = oldmm;
atomic_inc ( &oldmm->mm_count );
enter_lazy_tlb ( oldmm, next );
} else
switch_mm ( oldmm, mm, next );
if ( unlikely ( ! prev->mm ) ) {
prev->active_mm = NULL;
WARN_ON(rq->prev_mm);
rq->prev_mm = oldmm;
}
/* Here we just switch the register state and the stack. */
switch_to(prev, next, prev);
return prev;
}