os.timerfd_create: timers Linux precisos no Python

Publicado em: 27/09/2026
Tempo de leitura: 5 minutos
Ambiente Linux representando temporizadores com os.timerfd_create no Python

O os.timerfd_create permite criar temporizadores de alta precisão no Linux diretamente pelo Python. Em vez de depender apenas de time.sleep(), sinais ou loops que verificam o relógio repetidamente, o recurso devolve um descritor de arquivo que pode ser monitorado junto com sockets, pipes e outros eventos do sistema. Isso torna a API especialmente útil em servidores, agentes, coletores de métricas, automações e aplicações orientadas a eventos.

Neste guia, você vai entender como criar um timerfd, programar disparos únicos ou periódicos, integrar o descritor com select, interpretar o contador de expirações e evitar erros comuns de compatibilidade, bloqueio e encerramento.

O que é um timerfd?

No Linux, timerfd é uma interface do kernel que representa um temporizador como descritor de arquivo. Quando o tempo configurado expira, o descritor se torna legível. A leitura retorna um inteiro de 64 bits informando quantas expirações ocorreram desde a última leitura. Esse modelo combina muito bem com arquiteturas baseadas em eventos porque o mesmo loop pode aguardar dados de rede e temporizadores.

O Python expõe essa funcionalidade pelo módulo os em versões compatíveis. Como a implementação depende do Linux, o código deve verificar a presença de os.timerfd_create antes de usar a API.

import os

if not hasattr(os, "timerfd_create"):
    raise RuntimeError("timerfd não está disponível neste sistema")

Criando o descritor

A função recebe um relógio e flags. O relógio monotônico costuma ser a melhor escolha para intervalos, pois não sofre alterações quando o horário do sistema é corrigido. Já o relógio de tempo real é útil quando a regra depende de datas de calendário.

import os

fd = os.timerfd_create(os.CLOCK_MONOTONIC, os.TFD_CLOEXEC)
try:
    print("Descritor:", fd)
finally:
    os.close(fd)

A flag TFD_CLOEXEC impede que o descritor seja herdado acidentalmente por um programa iniciado com exec. Em serviços e ferramentas de linha de comando, essa proteção reduz vazamentos de recursos.

Configurando um disparo único

Depois de criar o descritor, use os.timerfd_settime para definir o primeiro disparo e, opcionalmente, um intervalo de repetição. Um intervalo igual a zero configura um timer de execução única.

import os
import struct

fd = os.timerfd_create(os.CLOCK_MONOTONIC, os.TFD_CLOEXEC)
try:
    os.timerfd_settime(fd, initial=2.0, interval=0.0)
    raw = os.read(fd, 8)
    expiracoes = struct.unpack("Q", raw)[0]
    print("Expirações:", expiracoes)
finally:
    os.close(fd)

A leitura bloqueia até o timer expirar, a menos que o descritor tenha sido criado em modo não bloqueante. O valor retornado geralmente é 1, mas pode ser maior se a aplicação demorou para ler um temporizador periódico.

Temporizadores periódicos

Para executar uma tarefa a cada segundo, informe o mesmo valor para o primeiro disparo e para o intervalo. O kernel mantém a contagem mesmo quando a aplicação fica momentaneamente ocupada.

import os
import struct

fd = os.timerfd_create(
    os.CLOCK_MONOTONIC,
    os.TFD_CLOEXEC | os.TFD_NONBLOCK,
)

os.timerfd_settime(fd, initial=1.0, interval=1.0)

try:
    for _ in range(5):
        while True:
            try:
                total = struct.unpack("Q", os.read(fd, 8))[0]
                print(f"{total} expiração(ões)")
                break
            except BlockingIOError:
                pass
finally:
    os.close(fd)

Esse exemplo usa uma espera ativa apenas para demonstrar o modo não bloqueante. Em aplicações reais, combine o descritor com select, poll ou outro mecanismo de eventos.

Integração com select

O principal benefício do timerfd aparece quando ele participa do mesmo loop que monitora outros descritores. Isso evita threads extras somente para controlar tempo.

import os
import select
import struct

fd = os.timerfd_create(
    os.CLOCK_MONOTONIC,
    os.TFD_CLOEXEC | os.TFD_NONBLOCK,
)
os.timerfd_settime(fd, initial=0.5, interval=0.5)

poller = select.poll()
poller.register(fd, select.POLLIN)

try:
    for _ in range(3):
        eventos = poller.poll(2000)
        for descritor, mascara in eventos:
            if descritor == fd and mascara & select.POLLIN:
                expiracoes = struct.unpack("Q", os.read(fd, 8))[0]
                print("Tick:", expiracoes)
finally:
    poller.unregister(fd)
    os.close(fd)

Relógio monotônico ou tempo real?

Use CLOCK_MONOTONIC para medir duração, timeout e repetição. Ele continua avançando de forma estável mesmo quando NTP ou um administrador altera o relógio civil. Use CLOCK_REALTIME somente quando a expiração precisa acompanhar o horário do calendário.

Para agendamento de tarefas de negócio, normalmente é melhor converter a data desejada para um intervalo e manter uma estratégia de revalidação. Mudanças de fuso, horário de verão e correções do sistema podem afetar timers vinculados ao relógio de tempo real.

Cancelamento e reprogramação

Um timer pode ser desarmado ao configurar o valor inicial como zero. Também é possível consultar a configuração anterior e reprogramar o mesmo descritor, o que reduz criação e fechamento repetidos.

os.timerfd_settime(fd, initial=0.0, interval=0.0)

Ao reprogramar, trate o descritor como um recurso compartilhado. Duas partes do código alterando o mesmo timer podem provocar condições de corrida e eventos inesperados.

Cuidados importantes

Leia exatamente oito bytes e interprete o resultado como inteiro de 64 bits. Sempre feche o descritor em um bloco finally ou em uma abstração própria. Em modo não bloqueante, trate BlockingIOError. Também registre atrasos: um contador maior que 1 indica que várias expirações ocorreram antes da leitura.

Não confunda timerfd com um agendador persistente. Se o processo reiniciar, o timer desaparece. Para tarefas que precisam sobreviver a reinicializações, use systemd timers, cron, uma fila de tarefas ou um banco de dados com retomada.

Quando usar

timerfd é indicado para loops de rede, proxies, coletores, daemons, simuladores e ferramentas que já trabalham com descritores. Para scripts simples, time.sleep() continua mais legível. Para código assíncrono portátil, considere asyncio no Python. Para entender medições confiáveis, veja perf_counter_ns no Python. Também vale revisar datas e horas com datetime e zoneinfo para fusos horários.

A documentação oficial do módulo os descreve a API disponível na versão instalada. Para detalhes do kernel, consulte a página timerfd_create(2).

Conclusão

os.timerfd_create aproxima o Python do modelo de eventos do Linux. Ele oferece temporizadores precisos, integração natural com poll e contagem de expirações sem exigir uma thread adicional. A melhor implementação verifica compatibilidade, prefere o relógio monotônico para intervalos, usa flags de segurança, interpreta corretamente os oito bytes retornados e fecha o descritor em qualquer cenário. Com esses cuidados, timerfd se torna uma ferramenta poderosa para aplicações de infraestrutura e automação.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Ambiente de desenvolvimento com múltiplas telas representando threads e GIL no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    sys._is_gil_enabled: descubra se o GIL está ativo

    Aprenda a verificar se o GIL está ativo no Python e a adaptar concorrência, testes e observabilidade para builds free-threaded.

    Ler mais

    Tempo de leitura: 5 minutos
    27/09/2026
    Terminal em notebook representando mudança de diretório com contextlib.chdir no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    contextlib.chdir: troque diretórios temporariamente

    Aprenda a usar contextlib.chdir no Python para alterar diretórios temporariamente com segurança, testes, scripts e automações previsíveis.

    Ler mais

    Tempo de leitura: 6 minutos
    26/09/2026
    Desenvolvedora usando Python com interpretadores isolados em ambiente de servidores
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    concurrent.interpreters: paralelismo isolado no Python

    Aprenda concurrent.interpreters no Python para criar intérpretes isolados, executar tarefas em paralelo e trocar dados com segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    26/09/2026
    Desenvolvedor usando Python para inspecionar arquivos com pathlib.Path.info
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pathlib.Path.info: inspecione arquivos com eficiência

    Aprenda pathlib.Path.info no Python para consultar arquivos e diretórios com eficiência.

    Ler mais

    Tempo de leitura: 7 minutos
    25/09/2026
    Estrutura de arquivos e código para os.path.splitroot no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    os.path.splitroot: separe raiz e unidade de caminhos

    Aprenda os.path.splitroot no Python para separar unidade, raiz e caminho restante com segurança em Windows, Linux e caminhos UNC.

    Ler mais

    Tempo de leitura: 4 minutos
    25/09/2026
    Código e estrutura de arquivos para filtros com glob.translate no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    glob.translate: converta padrões glob em regex

    Aprenda glob.translate no Python para converter padrões glob em regex e filtrar caminhos com recursão, separadores e segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    24/09/2026