Ficheiros e entrada/saída

Discos, volumes, dispositivos, polling, interrupções, DMA e caminho de um pedido.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

Duas chamadas read ao mesmo ficheiro podem ter custos muito diferentes. A primeira pode esperar pelo dispositivo; a seguinte pode encontrar os bytes na cache, uma cópia em memória. Acompanhar o pedido permite distinguir trabalho da CPU, transferência pelo hardware e espera pelo resultado.

Dispositivo, partição, volume e montagem

Um dispositivo de armazenamento contém blocos endereçáveis. Uma partição delimita uma região desse dispositivo. Um volume é uma unidade lógica de armazenamento, que pode corresponder a uma partição ou combinar outros recursos. Criar um sistema de ficheiros prepara estruturas para guardar nomes, metadados e blocos.

Montar associa um sistema de ficheiros a um ponto da árvore de nomes. Não copia todos os ficheiros para a RAM. Swap guarda certas páginas que saem da RAM e pode usar uma partição ou um ficheiro; não é uma pasta com os documentos do utilizador.

Uma unidade pode conter vários sistemas de ficheiros com propriedades diferentes. Um sistema temporário em memória é volátil; uma interface como /proc pode expor estado sem corresponder a ficheiros persistentes num disco.

HDD, SSD e tempos

Num disco magnético, uma leitura pode exigir mover a cabeça, esperar pela rotação e transferir dados. No modelo sem cache:

T=Tposicionamento+Trotac¸a˜o+Ttransfereˆncia.T = T_{\text{posicionamento}} + T_{\text{rotação}} + T_{\text{transferência}}.

A 7200 rotações por minuto, uma rotação demora 60/720060/7200 s, cerca de 8,33 ms. Se o setor inicial tiver posição uniforme, a espera média de rotação é metade, cerca de 4,17 ms. Com posicionamento de 5 ms e transferência de 1 ms, a leitura média demora cerca de 10,17 ms.

Um SSD não tem cabeça nem atraso de rotação. Ainda tem latência, limite de largura de banda e gestão interna de páginas e blocos de apagamento. Não apliques uma otimização de movimento de cabeça a um dispositivo sem esse movimento. TRIM comunica ao dispositivo que certos blocos lógicos já não são necessários, permitindo gestão interna mais eficiente; não é uma garantia de apagamento seguro imediato.

Latência mede quanto demora uma operação. Largura de banda mede bytes por unidade de tempo: transferir 1 MiB a 100 MiB/s demora cerca de 10 ms, sem contar latência inicial. Um dispositivo pode ter boa transferência sequencial e mau desempenho com muitas operações pequenas.

Controlador e driver

O controlador é hardware que comunica com o dispositivo e oferece registos de estado, controlo e dados; o driver é software que conhece esse protocolo e o apresenta ao resto do núcleo. A CPU pode usar instruções de I/O próprias ou registos do dispositivo mapeados em endereços, mas este memory-mapped I/O de hardware não é o mesmo que mapear um ficheiro com mmap: o primeiro acede a registos de um dispositivo, enquanto o segundo liga páginas do processo a conteúdo de um ficheiro ou objeto de memória.

As instruções e regiões que permitem controlar dispositivos precisam de proteção. Um programa normal pede acesso pelo sistema, em vez de reprogramar o disco diretamente.

Polling, interrupções e DMA

No polling, o software consulta repetidamente o estado até a operação poder avançar. É simples e pode servir para esperas muito curtas; em esperas longas consome CPU sem produzir trabalho útil.

Com interrupções, o dispositivo avisa quando há um evento. O driver inicia o pedido; a tarefa pode bloquear; uma interrupção de conclusão permite tratar o resultado e acordá-la. O custo inclui o tratador e eventual escalonamento. Uma interrupção não implica obrigatoriamente trocar para outro processo.

Com DMA, segue a sequência: a CPU prepara endereços, direção e tamanho; o hardware transfere dados entre dispositivo e memória; uma interrupção anuncia a conclusão; o driver trata o resultado e acorda a tarefa. A CPU não precisa de copiar cada byte com uma instrução, mas continua a preparar e gerir o pedido. DMA e interrupções combinam-se: a transferência pode terminar com uma interrupção.

Se um bloco de 64 KiB fosse tratado com uma interrupção por byte, teríamos 65536 interrupções. Um modelo com uma interrupção de conclusão por bloco teria uma, embora a operação ainda exija configuração e transferência. Agrupar pedidos reduz overhead e pode aumentar latência de entrega, por isso a escolha depende da aplicação.

Interfaces e tipos de dispositivo

Dispositivos de bloco, como armazenamento, trabalham com unidades endereçáveis e podem suportar acesso aleatório. Dispositivos de carácter, como uma porta série, apresentam um fluxo. Sockets têm uma interface própria para endereços e protocolos de rede.

Em /dev, entradas especiais identificam dispositivos e permitem certas operações com descritores. Números major e minor identificam uma classe de driver e uma instância ou subdispositivo. O nome da entrada não contém os dados de um ficheiro regular com todo o disco copiado.

ioctl permite operações específicas que não cabem em read ou write, como configurar um dispositivo. Uma interface uniforme simplifica programas, mas não torna todas as operações válidas em todos os descritores.

Bloqueante, não bloqueante e assíncrono

Na I/O bloqueante, a chamada pode suspender a tarefa até conseguir entregar o resultado. Na não bloqueante, retorna sem esperar pela disponibilidade futura, possivelmente com EAGAIN ou EWOULDBLOCK. Voltar a tentar num ciclo apertado recria espera ativa.

I/O assíncrona separa submissão e conclusão: o programa inicia o pedido e recebe depois indicação de que terminou. Não é apenas uma leitura não bloqueante que entregou menos bytes.

select ou poll podem esperar por disponibilidade em vários canais. Quando um está pronto, a aplicação pode tentar a operação, respeitando ainda o protocolo e a possibilidade de resultados parciais. I/O vetorizada, com readv ou writev, usa vários buffers numa chamada e reduz algumas cópias ou chamadas; não é garantia geral de atomicidade para qualquer destino.

Buffer, cache e spool

Um buffer guarda dados em trânsito e adapta velocidades ou tamanhos de transferência. Uma cache conserva dados para evitar repetir trabalho numa utilização futura. A mesma área pode desempenhar ambos os papéis, mas as finalidades são distintas.

Spooling guarda trabalhos para um dispositivo que os serve um de cada vez, como uma fila de impressão. Evita exigir que todas as aplicações usem a impressora diretamente e ao mesmo tempo.

Uma cache de páginas unificada permite coordenar acessos normais a ficheiros e mapeamentos sem manter desnecessariamente cópias independentes. Read-ahead antecipa dados numa leitura sequencial; descartar dados já consumidos pode evitar que uma leitura única expulse informação mais útil.

Seguir um read

Num modelo de leitura bloqueante de ficheiro regular, o pedido tem um início comum e depois dois percursos:

EtapaDados já em cacheDados por obter do dispositivo
Resolver o pedidoDescritor, posição e permissõesDescritor, posição e permissões
Obter os dadosEncontrar a página em memóriaSubmeter I/O pelo driver e controlador
EsperarSem espera pelo dispositivoTarefa bloqueia; outra pode usar CPU
Concluir I/ONão há pedido físico novoHardware conclui; núcleo atualiza a cache e torna a tarefa pronta
EntregarCopiar os bytes e atualizar posiçãoQuando a tarefa volta a correr, copiar e retornar

Falta na cache de ficheiros e falta de página do espaço virtual são conceitos diferentes. Também não assumas que O_NONBLOCK faz uma leitura de ficheiro regular retornar EAGAIN por faltar uma página na cache. A comparação dos três modos usa canais que suportem essas semânticas, como o pipe do exercício.

read bem-sucedido não prova que houve acesso físico ao disco. write bem-sucedido também não prova que os dados já sobreviveriam a uma falha de energia. A biblioteca pode ter buffers e o núcleo pode ter páginas sujas; persistência exige operações e garantias próprias, como fsync no descritor adequado.

Custos e falhas

O subsistema ordena pedidos, controla acesso, gere filas e buffers, regista erros e pode repetir operações recuperáveis. Uma leitura pode falhar por erro do dispositivo ou por descritor inválido; trata o retorno antes de usar o buffer.

Reduzir cópias, chamadas e interrupções pode melhorar desempenho. Medir só a CPU ignora esperas. Medir só uma execução pode observar apenas cache quente. Explicita quantidade de dados, padrão de acesso e estado da cache antes de comparar.

Sistemas também podem suspender dispositivos inativos para poupar energia. Dependências entre dispositivos importam: desligar um barramento afeta os seus filhos. Uma reserva exclusiva de dispositivo pode criar o mesmo problema de ordem de recursos que um lock.

STREAMS, usado em certos sistemas UNIX, organiza um canal com uma entrada para a aplicação, módulos e driver, cada um com filas de leitura e escrita. É um exemplo de composição por mensagens, não uma interface que devas assumir em todos os sistemas UNIX atuais.

Exercícios

Rotação, transferência e latência total

Um HDD roda a 7200 rpm, tem posicionamento médio de 5 ms e transfere a 100 MiB/s. Vamos ler 1 MiB sequencial numa única operação, com posição angular inicial uniforme, sem cache nem custos de fila. Calcula a espera média de rotação, o tempo de transferência e o tempo médio total. Por que não aplicarias o termo de rotação a um SSD?

Pista
Usa a mesma unidade antes de somar os três custos.
Solução

Uma rotação demora 60/7200 s, cerca de 8,33 ms. A posição uniforme dá espera média de metade: 4,17 ms. A transferência demora 1/100 s = 10 ms. O total é 5+4,17+10, cerca de 19,17 ms.

Não multiplicamos a latência pelo número de bytes: o modelo dá uma espera inicial seguida de transferência sequencial. Um SSD não tem partes rotativas, portanto esse termo não tem significado nele, embora continuem a existir latência e tempo de transferência.

Confere a tua resposta:

  • Converti 7200 rpm em período e usei metade para a espera média.
  • Obtive 10 ms para transferir 1 MiB.
  • Somei 5 ms de posicionamento e obtive cerca de 19,17 ms.
Voltar à explicação
Transferência com DMA

Com DMA, a CPU deixa de participar em toda a I/O? Explica o que pode acontecer desde a preparação até à conclusão.

Pista
Evitar copiar byte a byte não elimina a gestão.
Mais uma pista

Há configuração de endereços e tamanho, transferência e tratamento do resultado.

Solução

A CPU prepara o pedido; o hardware transfere dados entre dispositivo e memória; uma interrupção pode anunciar conclusão e o núcleo trata o resultado. DMA reduz o trabalho por byte, não elimina configuração, proteção ou erros.

Confere a tua resposta:

  • Expliquei o papel de configuração da CPU.
  • Identifiquei a transferência pelo hardware.
  • Distingui transferência de notificação de conclusão.

Erros frequentes

Dizer que DMA significa zero instruções de CPU, ou que DMA e interrupções são alternativas incompatíveis.

Voltar à explicação
O mesmo pedido em três modos

Um programa lê de um pipe vazio com a escrita aberta. Compara o que acontece com leitura bloqueante, não bloqueante e assíncrona: quem espera, o que retorna e como o programa fica a saber da conclusão.

Pista

A disponibilidade futura não existe em nenhum dos casos.

Mais uma pista

Sem dados e com escrita aberta, a leitura ainda não pode entregar bytes.

Solução

A bloqueante suspende a tarefa até haver dados ou EOF. A não bloqueante retorna sem esperar, com EAGAIN ou EWOULDBLOCK, e o programa decide quando voltar a tentar. A assíncrona regista o pedido e o programa recebe depois a indicação de conclusão. Repetir a não bloqueante num ciclo apertado recria espera ativa.

Confere a tua resposta:

  • Descrevi o que faz a chamada bloqueante.
  • Descrevi o retorno sem espera da não bloqueante.
  • Separei submissão de conclusão na assíncrona.

Erros frequentes

Chamar assíncrona a uma leitura curta, ou tratar EAGAIN como EOF.

Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.