Sistemas Operacionais

Escalonamento

Professor: Gabriel Soares Baptista

Introdução

Escalonar significa decidir quem usa a CPU, quando e por quanto tempo.

Em um sistema multiprogramado, essa decisão afeta diretamente:

  • a fluidez percebida pelo usuário
  • o aproveitamento da CPU
  • o tempo de espera dos processos
  • o consumo de energia e o cumprimento de prazos

O Problema Central

Imagine um único caixa atendendo uma fila inteira de clientes.

O problema principal não é como o caixa trabalha internamente, mas qual cliente ele atende primeiro.

No sistema operacional, a CPU é esse caixa. O escalonador precisa evitar dois extremos:

  • deixar processos curtos esperando demais
  • trocar de processo o tempo todo e desperdiçar CPU
Reflita

Se um processo curto ficar preso atrás de um processo muito longo, qual será o impacto na percepção de desempenho?

Quando o Escalonador Atua

Uma decisão de escalonamento costuma ocorrer em quatro momentos:

  1. criação de um novo processo
  2. término de um processo
  3. bloqueio por E/S ou sincronização
  4. término de E/S e retorno para a fila de prontos

Cada decisão tenta equilibrar responsividade, justiça e eficiência.

Processos CPU-bound e I/O-bound

Os processos alternam entre surtos de CPU e espera por E/S.

Tipo Comportamento Exemplo
CPU-bound Longos surtos de CPU renderização, simulação
I/O-bound Surtos curtos, muitas esperas banco de dados, shell

Processos I/O-bound se beneficiam de receber a CPU rapidamente para disparar a próxima operação de disco ou rede.

Preempção vs. Não Preempção

Não preemptivo

O processo mantém a CPU até terminar ou bloquear.

Preemptivo

O sistema pode retirar a CPU do processo atual, normalmente por interrupção de relógio.

Ideia-chave:

  • não preemptivo simplifica o controle
  • preemptivo melhora a responsividade

Métricas de Desempenho

Para comparar algoritmos, observamos principalmente:

  • Tempo de retorno: quanto tempo vai da chegada ao término
  • Tempo de espera: quanto tempo fica parado na fila de prontos
  • Tempo de resposta: quanto demora até a primeira execução
  • Vazão: quantos processos terminam por unidade de tempo
  • Utilização da CPU: fração do tempo em que a CPU está fazendo trabalho útil

$$T_{ret} = T_{termino} - T_{chegada}$$

$$T_{resp} = T_{primeira\_execucao} - T_{chegada}$$

Objetivos Dependem do Ambiente

Ambiente Objetivo dominante
Lote vazão e tempo de retorno
Interativo tempo de resposta
Tempo real cumprimento de prazos

Não existe algoritmo ideal para todos os cenários.

Um algoritmo ótimo para lote pode ser péssimo para um desktop interativo.

FCFS

First Come, First Served

Executa na ordem de chegada.

Vantagens:

  • implementação muito simples
  • comportamento previsível

Problema clássico:

  • processos curtos podem esperar demais atrás de um processo longo
  • surge o efeito comboio

FCFS e o Efeito Comboio

Se um processo longo entra primeiro, os curtos ficam todos atrás dele.

Consequências:

  • a CPU pode ficar ocupada com um único processo por muito tempo
  • processos I/O-bound demoram a emitir novas requisições
  • disco e rede podem ficar subutilizados
Processo Burst
$P_1$ 24 ms
$P_2$ 3 ms
$P_3$ 3 ms

No FCFS, a média de espera sobe bastante só por causa da ordem de chegada.

2026-04-06T18:00:20.436572 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/ 0 5 10 15 20 25 30 35 40 Tempo (ms) A B C D Efeito Comboio no FCFS Proc A (CPU-bound)

FCFS com Conta

Considere três processos chegando em $t=0$ na ordem $P_1, P_2, P_3$.

Processo Burst
$P_1$ 24 ms
$P_2$ 3 ms
$P_3$ 3 ms

Tempos de espera:

  • $T_{esp}(P_1)=0$
  • $T_{esp}(P_2)=24$
  • $T_{esp}(P_3)=27$

Média:

$$\frac{0+24+27}{3}=17\text{ ms}$$

Se invertermos a ordem para $P_2, P_3, P_1$, a média cai para:

$$\frac{0+3+6}{3}=3\text{ ms}$$

SJF

Shortest Job First

Escolhe primeiro a tarefa mais curta disponível.

Quando todas as tarefas chegam juntas, o SJF minimiza o tempo médio de espera e o tempo médio de retorno.

Intuição:

  • colocar tarefas curtas na frente reduz o atraso acumulado das demais

Limitação importante:

  • exige conhecer ou estimar o tempo de CPU necessário

Exemplo de Intuição do SJF

Quatro tarefas com tempos $8, 4, 4, 4$.

Ordem Retornos
FCFS: $A, B, C, D$ $8, 12, 16, 20$
SJF: $B, C, D, A$ $4, 8, 12, 20$

Resultado:

  • média em FCFS: 14
  • média em SJF: 11

O ganho aparece porque as tarefas curtas deixam de carregar o peso da longa logo no começo.

2026-04-06T18:07:56.320285 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/ A B C D FCFS (A, B, C, D) - Media 14 min 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 Tempo (min) A B C D SJF (B, C, D, A) - Media 11 min

SJF com Conta

Todos chegam em $t=0$.

Processo Burst Ordem no SJF
$P_1$ 6 ms 2
$P_2$ 8 ms 4
$P_3$ 7 ms 3
$P_4$ 3 ms 1

Tempos de espera no SJF:

  • $P_4=0$
  • $P_1=3$
  • $P_3=3+6=9$
  • $P_2=3+6+7=16$

Logo,

$$T_{esp}^{medio}=\frac{0+3+9+16}{4}=7\text{ ms}$$

SRTN

Shortest Remaining Time Next

É a versão preemptiva do SJF.

Quando chega uma nova tarefa, comparamos seu tempo com o tempo restante do processo atual.

Se a nova for menor, ela interrompe a execução corrente.

Isso melhora o atendimento de tarefas curtas que chegaram tarde, mas aumenta o número de chaveamentos de contexto.

Exemplo de Preempção no SRTN

  • $P_1$ começa em $t=0$ com burst 8
  • $P_2$ chega em $t=1$ com burst 4
  • restam 7 para $P_1$
  • como $4 < 7$, o escalonador interrompe $P_1$

O benefício é claro para tarefas curtas.

O custo também é claro:

  • mais interrupções
  • mais salvamento e restauração de contexto
2026-04-06T18:00:20.596951 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/ 0 2 4 6 8 10 12 Tempo (ms) A B SRTN: B interrompe A em t=2

SRTN com Conta

Considere:

Processo Chegada Burst
$P_1$ 0 8
$P_2$ 1 4
$P_3$ 2 9
$P_4$ 3 5

Retornos com SJF não preemptivo:

$$8, 11, 24, 14 \Rightarrow media=14{,}25\text{ ms}$$

Retornos com SRTN:

$$17, 4, 24, 7 \Rightarrow media=13\text{ ms}$$

O SRTN melhora a média porque interrompe o processo longo no momento certo.

Reflita

Em que tipo de máquina um custo alto de chaveamento faria o SRTN perder parte da sua vantagem?

Round-Robin

Cada processo recebe um quantum de CPU.

Se não terminar nesse intervalo, volta para o fim da fila.

É o algoritmo clássico de sistemas interativos porque:

  • ninguém monopoliza a CPU
  • todos recebem alguma chance rapidamente
  • o tempo de resposta tende a ser melhor que no FCFS
2026-04-06T18:00:20.648058 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/ 0 5 10 15 20 25 30 35 40 Tempo (ms) P1 P2 P3 Round-Robin com Quantum = 5 ms

Round-Robin com Conta

Considere $P_1=24$, $P_2=3$ e $P_3=3$, todos chegando em $t=0$, com quantum de 4 ms.

Linha do tempo:

  • $P_1$: de $0$ a $4$
  • $P_2$: de $4$ a $7$
  • $P_3$: de $7$ a $10$
  • $P_1$: continua depois até terminar em $30$

Tempos de resposta:

  • $P_1=0$
  • $P_2=4$
  • $P_3=7$

Logo,

$$T_{resp}^{medio}=\frac{0+4+7}{3}=3{,}66\text{ ms}$$

O Trade-off do Quantum

Quantum curto Quantum longo
mais responsividade menos overhead
mais trocas de contexto pior tempo de resposta
desperdício se o overhead for alto comportamento parecido com FCFS

Na prática, o quantum precisa ser grande o suficiente para não desperdiçar CPU e pequeno o suficiente para manter o sistema fluido.

2026-04-06T18:00:20.737436 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/ 0 20 40 60 80 100 Tamanho do Quantum (ms) 50 60 70 80 90 Eficiencia da CPU (%) Eficiencia Latencia 10 20 30 40 50 Tempo de Resposta Medio (ms) Trade-off do Round-Robin

Prioridades e Aging

Nem todos os processos têm a mesma urgência.

No escalonamento por prioridades, o processo mais prioritário executa primeiro.

Problema:

  • processos de baixa prioridade podem sofrer starvation

Solução clássica:

  • aging, que eleva gradualmente a prioridade de quem espera demais

Muitos sistemas combinam prioridades + Round-Robin dentro de cada fila.

2026-04-06T18:00:20.825660 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/ 0 1 2 3 4 5 6 7 Tempo (em quanta) Mais Alta Media Mais Baixa Filas Multinivel no estilo CTSS Nivel 0 (1q) Nivel 1 (2q) Nivel 2 (4q)

Outras Ideias Importantes

Escalonamento Garantido

Tenta entregar a cada processo sua fração prometida de CPU.

Loteria

Cada processo recebe bilhetes e disputa a CPU probabilisticamente.

Fair-Share

Distribui CPU por usuário ou grupo, não apenas por processo.

Essas abordagens atacam o problema da justiça por ângulos diferentes.

Exemplo rápido de Fair-Share:

  • Usuário 1 tem 4 processos
  • Usuário 2 tem 1 processo
  • ambos recebem 50% da CPU

Então cada processo do Usuário 1 recebe, em média, $12{,}5\%$ da CPU, enquanto o processo do Usuário 2 recebe $50\%$.

2026-04-06T18:00:20.900133 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/ 0 25 50 75 100 125 150 175 200 Numero de Sorteios 0 20 40 60 80 100 % de CPU Recebida Loteria: convergencia para a proporcao ideal Processo A (50%) Processo B (20%) Processo C (30%)

Tempo Real

Em sistemas de tempo real, o foco não é só terminar rápido.

O essencial é terminar antes do prazo. Condição de Escalonabilidade: Com $m$ eventos periódicos, onde o evento $i$ ocorre com período $P_i$ e precisa de $C_i$ segundos de CPU, o sistema é escalonável se:

$$\sum_{i=1}^{m} \frac{C_i}{P_i} \leq 1$$

Se a soma ultrapassa 1, a CPU exigida supera a capacidade disponível.

Exemplo:

$$\frac{50}{100}+\frac{30}{200}+\frac{100}{500}=0{,}85$$

Como $0{,}85 < 1$, o sistema ainda é escalonável.

2026-04-06T18:00:20.976017 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/ 0.0 0.2 0.4 0.6 0.8 1.0 1.2 Carga da CPU (1.0 = 100%) P1 P2 P3 15% livre LIMITE Escalonabilidade em Tempo Real P1: 50% P2: 15% P3: 20% Livre

Threads e Escalonamento

Threads de usuário

O kernel escolhe o processo, e a biblioteca local decide qual thread roda.

Threads de núcleo

O kernel enxerga cada thread individualmente e pode intercalá-las livremente.

Consequência:

  • threads de núcleo dão mais flexibilidade ao escalonador global
  • threads de usuário permitem políticas locais especializadas

Política vs. Mecanismo

Uma ideia central de projeto é separar:

  • mecanismo: o algoritmo e as estruturas do escalonador
  • política: como configurar prioridades, pesos, quanta e classes

Essa separação evita engessar o sistema e permite adaptar a estratégia ao contexto da aplicação.

Comparativo Final

Algoritmo Melhor uso Risco principal
FCFS lote simples efeito comboio
SJF lote com tempos conhecidos starvation de longos
SRTN cargas mistas com tarefas curtas overhead de preempção
Round-Robin sistemas interativos quantum mal ajustado
Prioridades cargas com urgências distintas starvation sem aging
Fair-Share / Loteria ambientes multiusuário calibração da justiça
Tempo real sistemas críticos perda de prazo

Fechamento

Escalonamento é o ponto onde o sistema operacional transforma uma CPU única em uma experiência aparentemente fluida para muitos processos ao mesmo tempo.

Escolher bem significa equilibrar:

  • justiça
  • responsividade
  • eficiência
  • previsibilidade

Próximos passos

Na próxima aula: 7 - deadlocks.

Veremos como processos podem ficar presos permanentemente ao disputar recursos e como o sistema tenta prevenir ou detectar esse colapso.