Nesta aula, vamos explorar os conceitos fundamentais sobre processos e escalonamento em sistemas operacionais. Entender como o sistema gerencia múltiplos programas concorrentes é essencial para a ciência da computação. Vamos abordar desde a definição de processo até os principais algoritmos de escalonamento.
O que é um Processo?
Um processo é um programa em execução. Ele inclui o código do programa, o contador de programa, as variáveis, os registradores e o contexto de hardware. Diferente de um programa, que é uma entidade passiva armazenada em disco, o processo é uma entidade ativa que possui um estado em um determinado instante.
Em sistemas operacionais modernos, cada processo possui seu próprio espaço de endereçamento, garantindo isolamento e proteção. O sistema operacional mantém uma tabela de processos, onde cada entrada (chamada de Process Control Block - PCB) armazena as informações necessárias para gerenciar o processo.
Estados de um Processo
- Novo (New): O processo está sendo criado.
- Pronto (Ready): O processo está carregado na memória e aguardando para ser executado pela CPU.
- Executando (Running): O processo está utilizando a CPU.
- Bloqueado (Waiting/Blocked): O processo está aguardando por um evento (como E/S ou um sinal).
- Terminado (Terminated): O processo terminou sua execução.
Escalonamento de Processos
O escalonamento é a atividade do sistema operacional que decide qual processo, na fila de prontos, receberá a CPU. O módulo responsável por essa decisão é chamado de escalonador (scheduler). Existem diferentes tipos de escalonamento: de longo prazo, médio prazo e curto prazo.
O escalonador de curto prazo (ou CPU scheduler) seleciona um processo da fila de prontos e aloca a CPU para ele. A frequência desse escalonamento é alta (a cada dezenas de milissegundos), sendo crucial para o desempenho do sistema.
Algoritmos de Escalonamento
Diversos algoritmos foram propostos para atender a diferentes critérios, como maximizar a utilização da CPU, minimizar o tempo de resposta e garantir equidade. Os principais incluem:
- First-Come, First-Served (FCFS): O primeiro processo a chegar é o primeiro a ser executado. Simples, mas pode causar o efeito convoy (processos curtos esperam por um longo processo).
- Shortest Job First (SJF): Seleciona o processo com o menor tempo de execução estimado. Pode ser preemptivo ou não. Ótimo em termos de tempo médio de espera, mas sofre de starvation para processos longos.
- Round Robin (RR): Cada processo recebe um quantum de tempo (time slice) e é executado em modo circular. Ideal para sistemas interativos, mas o desempenho depende do tamanho do quantum.
- Escalonamento por Prioridades: Cada processo recebe uma prioridade e a CPU é alocada para o processo de maior prioridade. Pode causar starvation para processos de baixa prioridade, resolvido com envelhecimento (aging).
- Múltiplas Filas (Multilevel Queue): Processos são divididos em diferentes filas com base em características, e cada fila pode usar seu próprio algoritmo.
Pontos Importantes sobre Escalonamento
- A troca de contexto (context switch) ocorre quando a CPU alterna de um processo para outro; ela consome tempo e overhead.
- O escalonamento pode ser preemptivo (o scheduler pode interromper um processo em execução) ou não preemptivo (o processo executa até terminar ou bloquear).
- Sistemas em tempo real requerem escalonamento com garantias de deadlines.
Exemplo Simples de Algoritmo Round Robin em Python
def round_robin(processos, quantum):
fila = processos[:]
tempo = 0
while fila:
processo = fila.pop(0)
if processo['tempo'] > quantum:
tempo += quantum
processo['tempo'] -= quantum
fila.append(processo)
print(f"Processo {processo['id']} executou por {quantum} unidades, tempo restante: {processo['tempo']}")
else:
tempo += processo['tempo']
print(f"Processo {processo['id']} finalizado no tempo {tempo}")
print(f"Tempo total de simulação: {tempo}")
# Exemplo de uso
processos = [{'id': 1, 'tempo': 10}, {'id': 2, 'tempo': 5}, {'id': 3, 'tempo': 8}]
round_robin(processos, 3)
Troca de Contexto
Quando o escalonador decide interromper um processo e iniciar outro, o sistema deve salvar o estado do processo atual (contexto) e carregar o estado do novo processo. Esse mecanismo é chamado de troca de contexto. O contexto inclui registradores, contador de programa, ponteiro de pilha, etc. A troca de contexto é um overhead puro, pois a CPU não realiza trabalho útil durante esse período.
Processos vs. Threads
Uma thread é a unidade básica de utilização da CPU, composta por um ID de thread, contador de programa, registradores e pilha. Threads de um mesmo processo compartilham o espaço de endereçamento e recursos, tornando a comunicação mais eficiente que entre processos. No entanto, a falta de proteção entre threads exige sincronização cuidadosa.
Sistemas operacionais modernos suportam threads em nível de usuário (ULT) e threads em nível de kernel (KLT). A maioria dos sistemas atuais utiliza threads nativas do kernel.
Perguntas Frequentes (FAQ)
- O que é um processo?
- É um programa em execução, incluindo código, dados, estado e contexto.
- Qual a diferença entre escalonamento preemptivo e não preemptivo?
- No preemptivo, o sistema pode interromper o processo em execução para alocar a CPU a outro. No não preemptivo, o processo mantém a CPU até terminar ou bloquear.
- O que é starvation?
- É quando um processo nunca recebe a CPU por existirem processos de maior prioridade sempre prontos. A técnica de aging aumenta a prioridade de processos que esperam muito tempo.
- O que é quantum no Round Robin?
- É o intervalo de tempo máximo que cada processo pode usar a CPU antes de ser interrompido. Deve ser balanceado: muito pequeno causa muitas trocas de contexto; muito grande degrada a interatividade.
Conclusão
Nesta aula, vimos os conceitos essenciais sobre processos e escalonamento em sistemas operacionais. Compreender esses tópicos é fundamental para projetar e analisar o desempenho de sistemas computacionais. Nos próximos dias, aprofundaremos em mecanismos de sincronização e comunicação entre processos.