Até aqui nesta série exploramos memória, CPU, pipeline, representação de dados e execução de programas — todos os componentes internos do computador. Mas um computador sem entrada e saída seria apenas uma calculadora fechada: incapaz de receber dados do mundo e incapaz de devolver resultados. Este artigo trata do problema que torna a E/S tão desafiadora, das três estratégias para resolvê-lo e de como calcular o impacto de cada uma no desempenho da CPU.
O problema fundamental da E/S
Dispositivos externos são ordens de grandeza mais lentos do que a CPU e a memória principal. A CPU opera em nanosegundos (GHz); um disco rígido responde em milissegundos; um teclado humano gera eventos a cada centenas de milissegundos. Toda a arquitetura de E/S existe para gerenciar essa incompatibilidade de velocidade sem desperdiçar os ciclos preciosos da CPU.
Dispositivos externos: da variedade à velocidade #
A primeira complicação de qualquer sistema de E/S é a diversidade dos dispositivos — cada um com velocidade, protocolo e comportamento completamente diferentes:
| Categoria | Exemplos | Taxa de transferência típica |
|---|---|---|
| Muito lentos | Teclado | bytes por segundo a poucas dezenas de B/s |
| Lentos | Mouse, impressora, UART | dezenas de B/s a KB/s |
| Médios | Disco rígido (HDD), USB 2.0 | MB/s a dezenas de MB/s |
| Rápidos | SSD SATA, rede Gigabit | centenas de MB/s |
| Muito rápidos | SSD NVMe, redes de alta velocidade | GB/s |
Faixas de taxa são apenas ordens de grandeza
As taxas acima servem como referência didática. Em sistemas reais, elas variam muito conforme interface, geração do barramento, controlador, protocolo, tamanho de bloco e padrão de acesso.
Quanto à função:
| Tipo | Exemplos |
|---|---|
| Entrada | Teclado, mouse, scanner, microfone, câmera |
| Saída | Monitor, impressora, alto-falante |
| Entrada/Saída | Disco rígido, pendrive USB, placa de rede, memória flash |
A figura abaixo mostra o modelo geral de um dispositivo de E/S, com seus componentes e a interface com o módulo de E/S da CPU:

A interface com o módulo de E/S ocorre na forma de sinais de controle, de dados e de estado. Os sinais de controle determinam a função que o dispositivo realizará, como enviar dados ao módulo de E/S (INPUT ou READ), aceitar dados do módulo de E/S (OUTPUT ou WRITE), informar o estado ou realizar alguma função de controle particular ao dispositivo (por exemplo, posicionar uma cabeça de disco). Os dados estão na forma de um conjunto de bits a serem enviados ou recebidos do módulo de E/S. Os sinais de estado indicam o estado do dispositivo. Alguns exemplos são READY/NOT-READY, para indicar se o dispositivo está pronto para uma transferência de dados. A lógica de controle, associada ao dispositivo, controla a operação do dispositivo em resposta ao módulo de E/S. O transdutor converte dados elétricos para outras formas de energia durante a saída e de outras formas para elétrico durante a entrada. Em geral, um buffer é associado ao transdutor para manter temporariamente os dados sendo transferidos entre o módulo de E/S e o ambiente externo.
A interface de E/S: o intermediário #
Entre a CPU e o dispositivo físico fica a interface de E/S (também chamada de controlador ou módulo de E/S). Na prática, a CPU não fala com o disco rígido; ela fala com o controlador do disco rígido. Esse circuito intermediário assume cinco responsabilidades vitais para isolar a CPU do caos do mundo exterior:
- Controle e temporização: Sincroniza o tráfego de dados entre recursos internos rápidos e dispositivos externos lentos.
- Comunicação com a CPU: Decodifica comandos, troca dados pelo barramento do sistema e relata o status.
- Comunicação com o dispositivo: Envia sinais elétricos ou comandos específicos do protocolo do periférico.
- Armazenamento temporário (Buffering): Acumula bits lentos que chegam do dispositivo até formar uma palavra de tamanho adequado (8, 16, 32 bits) para enviar à memória de uma só vez, compensando a diferença de velocidade.
- Detecção de erros: Checa problemas mecânicos (ex: papel preso) ou falhas de transmissão (bits corrompidos) e avisa a CPU.
Para realizar essas tarefas, toda interface possui ao menos três registradores internos mapeados para a CPU:
| Registrador | Função |
|---|---|
| Dados | Armazena o dado a ser transferido entre CPU ↔ dispositivo |
| Estado (status) | Indica a condição atual: pronto (ready), ocupado (busy) ou erro |
| Controle | Recebe comandos da CPU: iniciar operação, selecionar modo |
CPU ←————————————→ [ Interface de E/S ] ←————————→ Dispositivo
barramento [ Reg. Dados ] cabo/protocolo
[ Reg. Estado ]
[ Reg. Controle ]A figura abaixo oferece um diagrama de blocos geral de um módulo de E/S. O módulo conecta-se ao restante do computador por meio de um conjunto de linhas de sinal (por exemplo, linhas de barramento do sistema). Os dados transferidos de e para o módulo são armazenados em um ou mais registradores de dados. Também pode haver um ou mais registradores de estado que oferecem informações do estado atual.

Um registrador de estado também pode funcionar como um registrador de controle, para aceitar informações de controle detalhadas do processador. A lógica dentro do módulo interage com o processador por meio de um conjunto de linhas de controle. O processador usa as linhas de controle para enviar comandos ao módulo de E/S. Algumas das linhas de controle podem ser usadas pelo módulo de E/S (por exemplo, para sinais de arbitração e de estado). O módulo também precisa ser capaz de reconhecer e gerar endereços associados aos dispositivos que ele controla. Cada módulo de E/S tem um endereço exclusivo ou, se controlar mais de um dis- positivo externo, um conjunto exclusivo de endereços. Por fim, o módulo de E/S contém uma lógica específica à interface com cada dispositivo que ele controla.
Transmissão serial × paralela #
Os dados precisam trafegar de alguma forma entre interface e dispositivo. Dois paradigmas:
| Característica | Paralela | Serial |
|---|---|---|
| Bits por ciclo | 8, 16 ou 32 simultaneamente | 1 bit por vez |
| Distância típica | Curta (dentro do gabinete) | Longa (metros a km) |
| Número de fios | Muitos | Poucos (2 a 4) |
| Custo | Maior | Menor |
| Exemplos | Barramento interno, porta LPT | USB, RS-232, Ethernet, SATA |
A transmissão serial pode ser ainda:
- Síncrona: transmissor e receptor operam com uma referência temporal comum; no modelo clássico, isso aparece como um clock compartilhado. É mais eficiente, pois evita bits extras de sincronização por caractere.
- Assíncrona: não há clock compartilhado explícito entre as pontas; cada caractere é delimitado por bits especiais de início (start bit) e parada (stop bit) — padrão da UART (Universal Asynchronous Receiver-Transmitter).
Endereçamento de E/S: como a CPU acessa a interface #
Como a CPU acessa os registradores da interface de E/S? Há dois paradigmas:
E/S mapeada em memória (Memory-Mapped I/O): os registradores de E/S
recebem endereços dentro do mesmo espaço de endereçamento usado pela memória
principal. A CPU usa as mesmas instruções de acesso à memória (LDA, STR,
MOV…) para ler e escrever registradores de E/S. É simples e flexível.
Desvantagem: parte do mapa de endereços passa a ser ocupada por E/S, e não
por memória principal.
E/S independente (Port-Mapped I/O): existe um espaço de endereçamento
separado e exclusivo para E/S — as portas de E/S. Requer instruções dedicadas
(IN para leitura, OUT para escrita). Não consome endereços de memória; é o
modelo da arquitetura Intel x86 (portas de 0x0000 a 0xFFFF).
As três técnicas de E/S #
O problema central é: como a CPU sabe quando o dispositivo terminou uma operação e está pronto para transferir dados? Três estratégias evoluíram historicamente, cada uma mais eficiente que a anterior.
A figura abaixo ilustra as três técnicas de E/S: Polling, Interrupção e DMA. Cada técnica tem um modelo de interação distinto entre CPU, interface e dispositivo, com trade-offs claros em termos de eficiência e overhead. Serão exploradas em detalhes a seguir.

Polling — E/S programada (Busy-Wait) #
A CPU verifica continuamente o registrador de estado do dispositivo em um laço de espera ativa:
repita:
leia Reg_Estado do dispositivo
se Reg_Estado == PRONTO:
leia/escreva Reg_Dados
saia do laço
senão:
continue verificando (não faz nada útil)✅ Extremamente simples de implementar em software.
❌ Busy-wait: a CPU desperdiça todos os seus ciclos aguardando — não executa nenhum trabalho útil.
Desperdício catastrófico com polling
Em um sistema com clock de 1 GHz aguardando um disco com latência de 10 ms:
$$\text{Ciclos desperdiçados} = 10 \times 10^{-3}\,\text{s} \times 10^9\,\frac{\text{ciclos}}{\text{s}} = 10^7\text{ ciclos}$$Dez milhões de ciclos completamente ociosos — apenas esperando. Em sistemas de propósito geral com multitarefa, isso é inaceitável.
Interrupção — E/S por interrupção (Interrupt-Driven I/O) #
A CPU inicia a operação de E/S e retorna imediatamente ao seu trabalho. Quando o dispositivo conclui, ele envia um sinal de interrupção (IRQ — Interrupt Request). A CPU salva o estado atual, executa a rotina de tratamento (ISR) e retoma exatamente de onde parou:
sequenceDiagram
participant UCP
participant Dispositivo
participant ISR as ISR (Rotina de Tratamento)
UCP->>Dispositivo: Inicia operação (escreve em Reg. Controle)
UCP->>UCP: Continua executando outros processos
Dispositivo-->>UCP: Gera sinal IRQ ao concluir
UCP->>UCP: Salva contexto (PC, registradores)
UCP->>ISR: Desvia para rotina de tratamento
ISR->>ISR: Lê dado do Reg. Dados / trata resultado
ISR->>UCP: Restaura contexto
UCP->>UCP: Retoma execução de onde parou
✅ CPU não desperdiça ciclos em espera; executa trabalho útil em paralelo com E/S.
❌ Overhead de salvar e restaurar contexto a cada interrupção; muitas interrupções por segundo podem saturar a CPU.
Dois tipos de interrupção merecem atenção:
- Mascaráveis: podem ser desabilitadas temporariamente (
CLIno x86) — útil para seções críticas que não devem ser interrompidas. - Não-mascaráveis (NMI): sempre atendidas, mesmo com interrupções desabilitadas — reservadas para erros críticos de hardware (falha de energia, erro de memória).
DMA — Acesso Direto à Memória #
O controlador DMA é um circuito dedicado capaz de transferir blocos inteiros de dados entre a interface do dispositivo e a memória principal, sem que a CPU precise intervir a cada palavra transferida. A CPU apenas programa a operação (endereço, tamanho, direção), e o controlador DMA assume a movimentação do bloco pelo barramento.
O diagrama abaixo detalha as etapas da operação DMA, mostrando como a CPU programa o controlador, como o DMA rouba o barramento para transferir os dados e como a CPU é notificada ao final da transferência. O resultado é que a CPU fica praticamente livre durante toda a operação, exceto por um pequeno overhead inicial e uma interrupção final.
sequenceDiagram
participant UCP
participant DMA as Controlador DMA
participant MP as Memória Principal
participant IF as Interface / Dispositivo
UCP->>DMA: Programa DMA (endereço MP, tamanho, direção)
UCP->>UCP: Continua executando outras tarefas
DMA->>UCP: Solicita uso do barramento
UCP->>DMA: Concede o barramento
Note over UCP,DMA: Cycle stealing / cessão temporária do barramento
DMA->>IF: Coordena leitura/escrita do dispositivo
DMA->>MP: Transfere o bloco pela memória
DMA-->>UCP: Interrupção ao final da transferência
O diagrama acima detalha as oito etapas da operação DMA. Nas duas primeiras, a CPU ainda está no controle: ela programa o controlador DMA informando o endereço de destino na memória principal, a quantidade de dados a transferir e a direção da operação (leitura ou escrita). A partir daí, ela simplesmente continua executando outras tarefas — esse é o ganho fundamental em relação às técnicas anteriores.
Quando o controlador DMA está pronto para iniciar a transferência, ele precisa usar o barramento do sistema, que pertence à CPU. Por isso ele solicita o barramento (passo 3), e a CPU o concede (passo 4), suspendendo temporariamente seu próprio acesso a ele — o chamado cycle stealing, indicado pela nota no diagrama. Concedido o barramento, o DMA age de forma autônoma: coordena a leitura ou escrita junto à interface do dispositivo (passo 5) e transfere o bloco diretamente para a memória principal (passo 6), sem que a CPU participe palavra por palavra. Ao final, o controlador DMA envia uma interrupção à CPU (passo 7), sinalizando que a transferência terminou e que o dado já está disponível na memória.
Vale notar que o diagrama é uma simplificação intencional: ele representa a transferência como um único bloco contínuo, ocultando o fato de que, no cycle stealing real, a solicitação e a concessão do barramento se repetem para cada palavra transferida. A nota a seguir detalha essa distinção.
Roubo de ciclo — Cycle Stealing vs. Modo Rajada (Burst Mode)
O DMA pode operar em dois modos distintos de controle do barramento:
-
Cycle stealing (roubo de ciclo): o controlador DMA solicita o barramento, rouba 1 ciclo, transfere 1 palavra e devolve o barramento imediatamente. A CPU retoma brevemente, e o processo se repete para cada palavra do bloco. O impacto sobre a CPU é pulverizado ao longo do tempo, mas ela nunca fica completamente livre durante a transferência.
-
Modo rajada (burst mode): o DMA toma o barramento uma única vez e mantém o controle por toda a duração da transferência. A CPU fica suspensa durante todo o bloco, mas o barramento é usado de forma muito mais eficiente (sem a sobrecarga de múltiplas negociações).
O diagrama acima representa, de forma simplificada, o modo rajada — a solicitação e concessão aparecem uma única vez. No cycle stealing real, essa negociação se repete palavra por palavra. Em ambos os casos, a CPU não participa da transferência em si e é notificada apenas ao final, via interrupção.
A eficiência desse “roubo” depende de como o DMA está fisicamente conectado à placa-mãe. Existem três configurações arquiteturais clássicas:
- Barramento Único (Controlador Solto): O DMA e o dispositivo compartilham o mesmo barramento do sistema. Para ler um dado do disco para a RAM, o dado trafega do Disco para o DMA e, em seguida, do DMA para a RAM. Isso usa o barramento duas vezes, suspendendo a CPU em ambos os momentos.
- Barramento Único (Controlador Integrado): O DMA e a interface de E/S formam um único componente. O dado vai direto desse controlador para a RAM. A CPU é suspensa apenas uma vez.
- Barramento de E/S Dedicado: O sistema possui o barramento principal (CPU-Memória) e um barramento secundário específico para periféricos (como o PCI Express). O DMA atua como uma “ponte” entre os dois. Transferências entre dispositivos no barramento secundário não afetam a CPU, e o envio para a RAM rouba o mínimo de ciclos possível.
✅ CPU praticamente livre durante a transferência de blocos grandes.
❌ Requer hardware dedicado (controlador DMA); maior custo e complexidade.
Tabela comparativa #
| Característica | Polling | Interrupção | DMA |
|---|---|---|---|
| Complexidade de HW | Mínima | Média | Alta |
| Complexidade de SW | Baixa | Média | Média |
| Eficiência da CPU | Muito baixa | Boa | Muito alta para blocos grandes |
| Velocidade de E/S | Limitada | Média | Alta |
| Overhead por transferência | Alto (laço contínuo) | Médio (contexto por evento) | Baixo (CPU não participa de cada palavra) |
| Aplicações típicas | MCUs simples | Teclado, mouse, temporizadores | Disco, rede, áudio/vídeo |
Como escolher a técnica certa
- Polling: dispositivo com resposta muito rápida (< 1 µs) onde o custo de uma interrupção seria maior que a espera, ou sistemas embarcados muito simples sem multitarefa.
- Interrupção: maioria dos dispositivos de propósito geral — teclado, mouse, UART, temporizadores.
- DMA: transferências grandes e frequentes — discos rígidos, SSDs, placas de rede, áudio e vídeo.
Calculando o overhead de E/S #
O overhead de E/S mede a fração dos ciclos de CPU consumida para tratar operações de E/S:
$$\text{Overhead (\%)} = \frac{\text{operações/s} \times \text{ciclos/operação}}{\text{ciclos totais/s}} \times 100$$Onde:
$$\text{operações/s} = \frac{\text{taxa de transferência (B/s)}}{\text{tamanho da unidade transferida (B)}}$$$$\text{ciclos totais/s} = f_{\text{clock}}$$Os passos para resolver qualquer problema de overhead:
- Calcular quantas operações de E/S ocorrem por segundo (taxa ÷ tamanho da unidade)
- Multiplicar pelo número de ciclos de CPU gastos por operação
- Dividir pela frequência do clock
- Multiplicar por 100 para obter o percentual
Exemplo — Overhead de interrupções de um mouse
Um mouse USB envia 40 relatórios por segundo, cada um com 4 bytes. A CPU (1 GHz) gasta 1000 ciclos por interrupção.
Com interrupção:
$$\text{Overhead} = \frac{40 \times 1000}{1 \times 10^9} = \frac{40.000}{10^9} = 0{,}004\%$$Praticamente desprezível — a CPU gasta apenas 4 em cada 100.000 ciclos tratando o mouse.
Com polling a 1 kHz (1000 verificações/s), 100 ciclos por verificação:
$$\text{Overhead}_{\text{polling}} = \frac{1000 \times 100}{10^9} = 0{,}01\%$$Também pequeno para o mouse — mas imagine aplicar polling a um disco SSD NVMe lendo a GB/s: o polling seria catastrófico.
Observação didática sobre o exemplo a seguir
O cálculo abaixo usa um modelo simplificado e historicamente clássico: uma interrupção por bloco pequeno e tamanho fixo de transferência. Isso é útil para comparar as três técnicas de E/S, mas dispositivos modernos — especialmente SSDs NVMe e redes de alta velocidade — usam mecanismos mais sofisticados de fila, agrupamento de interrupções e transferência.
Exemplo — Lendo 1 MB do disco: comparação das três técnicas
Sistema com CPU de 1 GHz lendo 1 MB de um disco com latência de 5 ms e taxa de 100 MB/s.
Com Polling: Tempo de transferência: \(1\,\text{MB} / 100\,\text{MB/s} = 10\,\text{ms}\)
$$\text{Ciclos desperdiçados} = (5 + 10) \times 10^{-3} \times 10^9 = 15 \times 10^6\text{ ciclos}$$CPU praticamente bloqueada durante toda a operação.
Com Interrupção (modelo didático: 1 interrupção por setor de 512 B):
$$\text{Interrupções} = \frac{1\,\text{MB}}{512\,\text{B}} = 2048\text{ interrupções}$$$$\text{Overhead} = 2048 \times 100\,\text{ciclos} = 204.800\text{ ciclos}$$
CPU livre durante a maior parte da operação, mas ainda precisa tratar muitas interrupções.
Com DMA: CPU programa o DMA uma única vez (custo ≈ dezenas de ciclos), DMA transfere todo o bloco autonomamente, 1 única interrupção ao final.
$$\text{Overhead}_{\text{DMA}} \approx \text{programação} + 100\text{ ciclos (1 IRQ)} \ll 204.800$$| Técnica | Overhead estimado |
|---|---|
| Polling | 15.000.000 ciclos (CPU bloqueada) |
| Interrupção | ~204.800 ciclos |
| DMA | ~dezenas + 100 ciclos |
Exemplo — Identificando técnicas a partir de pseudo-código
Três implementações distintas para transferir dados de um dispositivo:
Implementação 1: Configurar dispositivo → Iniciar leitura → aguardar em laço até concluir → Armazenar → Processar. → Polling — a palavra-chave é o laço de espera ativa antes do armazenamento.
Implementação 2: Configurar dispositivo → Configurar rotina de ISR → Continuar executando; quando IRQ chegar, ISR armazena dados e retorna → Processar. → Interrupção — a palavra-chave é a rotina de tratamento (ISR) disparada pelo dispositivo.
Implementação 3: Configurar controlador DMA (endereços, tamanho) → Habilitar → Controlador transfere sem intervenção da CPU → Interrupção ao fim → Processar. → DMA — a palavra-chave é “sem intervenção da CPU” durante a transferência.
Cenários recomendados:
- Polling: controle exato do momento de leitura sem latências de interrupção (aquisição de dados em tempo real crítico).
- Interrupção: dispositivos assíncronos de velocidade moderada (mouse, teclado, UART).
- DMA: altos volumes de dados contínuos (vídeo, disco, rede).
Conclusão e próximos artigos #
A E/S é o ponto onde o computador encontra o mundo físico — e gerenciar essa fronteira é fundamentalmente um problema de diferença de velocidade. Polling desperdiça CPU em espera ativa; interrupções delegam a notificação ao hardware, liberando a CPU para trabalho útil; DMA libera a CPU completamente para blocos grandes. A escolha certa depende do volume de dados, da frequência dos eventos e da tolerância ao overhead.
No próximo artigo, vamos explorar as arquiteturas avançadas de processadores — RISC vs CISC, métricas de desempenho, a taxonomia de Flynn e como os processadores modernos partem para o paralelismo em múltiplos níveis. Fique ligado!
Até lá!