Nesta aula, mergulhamos no conceito de processos em sistemas operacionais. Um processo é essencialmente um programa em execução, mas envolve muito mais do que apenas o código: ele carrega consigo um contexto completo, incluindo registradores, contador de programa, pilha e espaço de endereçamento. Compreender como o sistema operacional gerencia múltiplos processos é fundamental para entender o funcionamento de qualquer sistema computacional moderno.
O que é um processo?
Um processo pode ser definido como uma unidade de trabalho em um sistema operacional. Diferente de um programa (que é uma entidade passiva armazenada em disco), o processo é uma entidade ativa que possui um estado de execução. Cada processo é representado internamente por uma estrutura chamada bloco de controle de processo (Process Control Block – PCB), que contém todas as informações necessárias para gerenciar sua execução:
- Identificador único (PID)
- Estado atual do processo
- Registradores da CPU
- Contador de programa
- Informações de escalonamento
- Informações de gerenciamento de memória
- Informações de I/O
O PCB é criado quando o processo é iniciado e atualizado continuamente pelo sistema operacional durante sua execução.
Estados de um processo
Ao longo de sua vida, um processo transita entre diferentes estados. O modelo clássico de cinco estados é amplamente utilizado:
- Novo (New): O processo está sendo criado.
- Pronto (Ready): O processo está carregado na memória e aguarda a vez de usar a CPU.
- Executando (Running): O processo está sendo executado pela CPU.
- Bloqueado (Waiting/Blocked): O processo está aguardando a ocorrência de algum evento (como I/O ou sinal) para continuar.
- Terminado (Terminated): O processo concluiu sua execução.
As transições entre esses estados são controladas pelo escalonador e pelo dispatcher do sistema operacional.
Escalonamento de processos
O escalonamento de CPU é a atividade que decide qual dos processos prontos será executado. O módulo responsável é o escalonador de curto prazo (short‑term scheduler). Existem duas categorias principais de escalonamento: preemptivo e não preemptivo.
- Não preemptivo (cooperativo): o processo executa até bloquear ou terminar voluntariamente.
- Preemptivo: o sistema operacional pode interromper o processo a qualquer momento para dar a CPU a outro processo.
Alguns algoritmos clássicos de escalonamento:
| Algoritmo | Preemptivo? | Descrição | Problemas |
|---|---|---|---|
| FCFS (First‑Come, First‑Served) | Não | Executa na ordem de chegada | Efeito comboio, tempo médio de espera alto |
| SJF (Shortest Job First) | Não / Sim (SRTF) | Executa o processo com menor próximo surto de CPU | Impossível saber o surto antecipadamente; pode causar starvation |
| Round Robin | Sim | Distribui um quantum de tempo para cada processo em ordem circular | Quantum muito pequeno → muitas trocas; muito grande → interativo lento |
| Escalonamento por Prioridade | Sim / Não | Processos com prioridade mais alta executam primeiro | Starvation de processos de baixa prioridade (solucionável com envelhecimento) |
A escolha do algoritmo depende do ambiente: sistemas interativos favorecem Round Robin; sistemas batch podem usar FCFS ou SJF.
Troca de contexto (Context Switch)
Quando o escalonador decide interromper um processo e iniciar outro, ocorre uma troca de contexto. O sistema operacional salva o estado atual do processo (registradores, contador de programa, etc.) no seu PCB e carrega o estado do próximo processo. Essa operação tem um custo em tempo de CPU, pois envolve manipulação de estruturas de dados e geralmente exige a invalidação de caches. Sistemas operacionais modernos otimizam esse processo ao máximo, mas trocas excessivas (por exemplo, com quantum muito pequeno no Round Robin) podem degradar o desempenho.
Concorrência e paralelismo
Em sistemas com um único núcleo, a ilusão de execução simultânea é obtida por meio da concorrência: o sistema intercala rapidamente a execução dos processos, dando a impressão de paralelismo. Já em sistemas multicore, é possível o paralelismo real, com múltiplos processos executando ao mesmo tempo em núcleos diferentes.
No entanto, a concorrência traz desafios: acesso concorrente a recursos compartilhados pode levar a condições de corrida (race conditions). Para evitar isso, são empregados mecanismos de exclusão mútua, como semáforos, mutexes e monitores.
Comunicação entre processos (IPC)
Muitas vezes, processos precisam trocar dados ou se sincronizar. O sistema operacional oferece diversos mecanismos de comunicação entre processos (IPC – Inter‑Process Communication):
- Pipe: canal unidirecional de comunicação entre processos relacionados.
- FIFO (named pipe): similar ao pipe, mas permite comunicação entre processos não relacionados via um arquivo especial.
- Memória compartilhada: região de memória acessível por múltiplos processos; requer sincronização explícita.
- Filas de mensagens: troca de mensagens através de uma fila gerenciada pelo kernel.
- Socket: usado para comunicação entre processos em diferentes máquinas, mas também localmente.
Cada mecanismo tem suas vantagens e cenários de uso. A memória compartilhada é a mais rápida, mas exige controle de concorrência; as filas de mensagens são mais seguras, embora introduzam overhead.
Exemplo: criação de processos em Python
A biblioteca multiprocessing do Python permite criar processos de forma simples:
import multiprocessing
import os
def task(name):
print(f"Processo {name} (PID: {os.getpid()}) em execução")
if __name__ == "__main__":
p1 = multiprocessing.Process(target=task, args=("A",))
p2 = multiprocessing.Process(target=task, args=("B",))
p1.start()
p2.start()
p1.join()
p2.join()
print("Ambos os processos finalizaram")
Este script cria dois processos filhos que executam a função task concorrentemente. A chamada join() garante que o processo principal aguarde o término de cada filho.
Perguntas Frequentes
Qual a diferença entre processo e thread?
Um processo possui seu próprio espaço de endereçamento, enquanto uma thread compartilha o mesmo espaço de endereçamento com outras threads do mesmo processo. Threads são mais leves e a comunicação entre elas é mais eficiente, mas exigem cuidado com acesso concorrente a dados globais.
O que é starvation em escalonamento?
Starvation (ou inanição) ocorre quando um processo nunca recebe tempo de CPU porque outros processos com prioridade maior sempre são escolhidos. Técnicas como envelhecimento (aging) aumentam gradualmente a prioridade de processos que esperam há muito tempo para evitar esse problema.
Como funciona o algoritmo Round Robin?
Round Robin atribui a cada processo um intervalo fixo de tempo chamado quantum. A fila de prontos é tratada como circular. Se um processo não termina dentro do quantum, a CPU é retirada dele e vai para o próximo. É justo e evita starvation, mas o desempenho depende da escolha adequada do quantum.
Nesta aula, consolidamos os fundamentos do gerenciamento de processos: desde a representação interna (PCB) até os mecanismos de comunicação e sincronização. Esses conceitos são a base para o projeto e a análise de sistemas operacionais modernos, e serão explorados em maior profundidade nas próximas aulas.