Capítulo 11: Sistemas Operacionais: Processos, Threads, Deadlocks e Memória Virtual

Módulo 01: Fundamentos da Computação • Ciência da Computação Formal


🗺️ 1. Arquitetura do Sistema Operacional e Níveis de Privilégio

flowchart TD
    subgraph USER["Espaço do Usuário (Ring 3)"]
        APPS["Aplicações / Processos em Execução"]
    end

    SYSCALL["Chamadas de Sistema (Syscalls / Interrupções de Software)"]

    subgraph KERNEL["Espaço do Kernel (Ring 0)"]
        SCHED["Escalonador de CPU (Round Robin / CFS)"]
        MMU["Gerenciador de Memória Virtual & Paginação"]
        FS["Sistema de Arquivos e Drivers I/O"]
    end

    HW["Hardware (CPU, MMU, Discos, Placas de Rede)"]

    APPS --> SYSCALL
    SYSCALL --> KERNEL
    KERNEL --> HW

    style USER fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style KERNEL fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
    style HW fill:#fff3e0,stroke:#ff9800,stroke-width:2px

🏛️ 2. Fundamentação Teórica

O Sistema Operacional (SO) atua como árbitro de recursos de hardware e provedor de abstrações para as aplicações, garantindo isolamento de falhas e compartilhamento seguro da CPU e memória.

2.1 Processos vs Threads: O Ciclo de Vida e PCB

  • Processo: Uma instância de programa em execução com seu próprio espaço de endereçamento de memória isolado, descritores de arquivos e credenciais de segurança. É gerenciado pelo SO através do PCB (Process Control Block).
  • Thread: A menor unidade de execução escalonável pela CPU. Threads pertencentes ao mesmo processo compartilham o mesmo espaço de memória Heap, mas possuem pilhas (Stacks) e conjuntos de registradores exclusivos.

Diagrama de Transição de Estados: \(\text{Novo} \longrightarrow \text{Pronto} \underset{\text{Preempção}}{\overset{\text{Despacho}}{\rightleftharpoons}} \text{Executando} \overset{\text{I/O Bloqueante}}{\longrightarrow} \text{Esperando} \longrightarrow \text{Pronto}\)


2.2 Memória Virtual, Paginação e TLB

A memória virtual abstrai a RAM física, dando a cada processo a ilusão de possuir uma memória contígua e privativa (de até 128 TB em arquiteturas de 64 bits):

  1. Páginas e Molduras: A memória lógica é dividida em Páginas (tipicamente de 4 KB), mapeadas em Molduras (Frames) da memória física.
  2. Translation Lookaside Buffer (TLB): Cache de hardware associativa de alta velocidade dentro da MMU da CPU que armazena as traduções de endereços mais recentes.
  3. Falta de Página (Page Fault): Se o bit de validade indicar que a página não está na RAM, a CPU gera uma interrupção de hardware (Trap), o kernel suspende o processo e transfere a página do disco (Swap/Paging File) para a memória.

2.3 As Quatro Condições de Coffman para Deadlock

Um Deadlock (impasse permanente) ocorre se e somente se as quatro condições a seguir coexistirem simultaneamente:

  1. Exclusão Mútua: O recurso só pode ser retido por um processo por vez.
  2. Posse e Espera (Hold and Wait): Um processo retendo um recurso aguarda a liberação de recursos adicionais alocados a outros processos.
  3. Não-Preempção: Recursos alocados não podem ser tomados compulsoriamente antes de sua liberação voluntária.
  4. Espera Circular: Existe uma cadeia ${P_0, P_1, \dots, P_n}$ onde $P_0$ espera por recurso retido por $P_1$, e $P_n$ espera por $P_0$.

💻 3. Simulação de Escalonador Round-Robin em Python

from collections import deque
from typing import List, Dict

def escalonamento_round_robin(processos: List[Dict], quantum: int):
    fila = deque([p.copy() for p in processos])
    tempo_atual = 0
    ordem_execucao = []

    while fila:
        proc = fila.popleft()
        execucao = min(proc["tempo_restante"], quantum)
        
        ordem_execucao.append((proc["nome"], tempo_atual, tempo_atual + execucao))
        proc["tempo_restante"] -= execucao
        tempo_atual += execucao

        if proc["tempo_restante"] > 0:
            fila.append(proc)
        else:
            proc["tempo_conclusao"] = tempo_atual

    return ordem_execucao, tempo_atual

if __name__ == "__main__":
    tabela_processos = [
        {"nome": "P1", "tempo_restante": 10},
        {"nome": "P2", "tempo_restante": 5},
        {"nome": "P3", "tempo_restante": 8},
    ]

    quantum = 3
    historico, tempo_total = escalonamento_round_robin(tabela_processos, quantum)

    print(f"=== SIMULAÇÃO ROUND-ROBIN (Quantum = {quantum}ms) ===")
    for nome, inicio, fim in historico:
        print(f"Tempo {inicio:02d} - {fim:02d}ms : Processo {nome}")
    print(f"Tempo Total de Execução: {tempo_total}ms")