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.







