os.timerfd_create: timers Linux precisos en Python

Publicado el: 27/09/2026
Tempo de leitura: 5 minutos
Entorno Linux que representa temporizadores con os.timerfd_create en Python

os.timerfd_create permite crear temporizadores de alta precisión en Linux directamente desde Python. En lugar de depender únicamente de time.sleep(), señales o bucles que consultan el reloj constantemente, la aplicación obtiene un descriptor de archivo que se vuelve legible cuando vence el plazo configurado.

Este enfoque encaja especialmente bien en servidores, agentes, recolectores de métricas, herramientas de red, automatizaciones y servicios orientados a eventos, porque el temporizador puede vigilarse junto con sockets, pipes y otros descriptores del sistema.

En esta guía aprenderás a crear un timerfd, configurar disparos únicos y periódicos, integrarlo con select, interpretar el contador de expiraciones y evitar problemas de compatibilidad, bloqueo y liberación de recursos.

¿Qué es timerfd?

timerfd es una interfaz del kernel de Linux que representa un temporizador como descriptor de archivo. Cuando el tiempo vence, el descriptor queda listo para lectura. Al leer ocho bytes se obtiene un entero sin signo de 64 bits que indica cuántas expiraciones ocurrieron desde la lectura anterior.

Esto resulta importante en temporizadores periódicos. Si el proceso está ocupado y pasan tres intervalos antes de leer, el contador puede devolver 3. Así, la aplicación puede detectar retrasos, ticks acumulados o un loop de eventos saturado.

La API solo existe en sistemas y versiones compatibles. Como timerfd es específico de Linux, conviene comprobar su disponibilidad antes de ejecutar el código.

import os

if not hasattr(os, "timerfd_create"):
    raise RuntimeError("timerfd no está disponible")

Crear el descriptor

La función recibe un reloj y algunas flags. Para intervalos y timeouts, el reloj monotónico suele ser la opción correcta porque no cambia cuando se ajusta la hora civil del sistema.

import os

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

TFD_CLOEXEC evita que el descriptor sea heredado accidentalmente por otro programa ejecutado mediante una operación de tipo exec. Es una protección recomendable para servicios y herramientas de consola.

Configurar un disparo único

Después de crear el descriptor se programa con os.timerfd_settime. El valor inicial determina el primer disparo. El intervalo determina si se repite. Un intervalo igual a cero crea un temporizador de una sola ejecución.

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)
    datos = os.read(fd, 8)
    expiraciones = struct.unpack("Q", datos)[0]
    print("Expiraciones:", expiraciones)
finally:
    os.close(fd)

La lectura bloquea hasta el vencimiento, salvo que el descriptor se haya creado en modo no bloqueante. Después de leer, el descriptor sigue abierto y puede reprogramarse.

Temporizadores periódicos

Para generar un evento cada segundo, configura el mismo valor para el retraso inicial y el intervalo. El kernel mantiene el calendario aunque la aplicación tarde en procesar un evento.

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:
    recibidas = 0
    while recibidas < 5:
        try:
            cantidad = struct.unpack("Q", os.read(fd, 8))[0]
            recibidas += cantidad
            print("Ticks:", cantidad)
        except BlockingIOError:
            continue
finally:
    os.close(fd)

El bucle activo sirve solo como demostración. En una aplicación real, registra el descriptor en poll, select o un mecanismo equivalente para esperar sin consumir CPU.

Integración con poll

La principal ventaja de timerfd es que participa en el mismo loop que los descriptores de red o IPC. No hace falta crear un hilo exclusivo para dormir y despertar el proceso principal.

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:
    procesadas = 0
    while procesadas < 3:
        for descriptor, mascara in poller.poll(2000):
            if descriptor == fd and mascara & select.POLLIN:
                cantidad = struct.unpack("Q", os.read(fd, 8))[0]
                procesadas += cantidad
                print("Evento de timer:", cantidad)
finally:
    poller.unregister(fd)
    os.close(fd)

El mismo poller puede incluir sockets de escucha, conexiones de clientes, pipes o eventfd. El temporizador pasa a ser otro evento dentro de un despachador centralizado.

Reloj monotónico o tiempo real

Usa CLOCK_MONOTONIC para timeouts, reintentos, verificaciones de salud, intervalos y tareas periódicas. Avanza de forma estable incluso si NTP o un administrador modifica la hora del sistema.

Usa CLOCK_REALTIME cuando la fecha de calendario sea parte esencial de la regla. Aun así, considera cambios de zona horaria, horario de verano y correcciones del reloj. Para programación de negocio, suele ser más seguro guardar la fecha objetivo y volver a validarla.

Desarmar y reprogramar

Un timer puede desactivarse configurando el valor inicial en cero. El mismo descriptor puede activarse nuevamente después.

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

Reutilizar el descriptor reduce operaciones, pero exige una propiedad clara. Si varios componentes reprograman el mismo timer sin coordinación, un plazo puede sustituir silenciosamente a otro. Encapsula el recurso en una clase o mantenlo bajo control de un único loop.

Errores y limpieza

Lee exactamente ocho bytes e interpreta el resultado como entero de 64 bits. En modo no bloqueante, captura BlockingIOError. Si el contador es mayor que 1, registra esa información: indica que varias expiraciones se acumularon antes del procesamiento.

Cierra siempre el descriptor mediante finally, un context manager o un método de ciclo de vida. Utiliza TFD_CLOEXEC salvo que la herencia sea intencional.

timerfd no es un planificador persistente. Si el proceso o la máquina se reinicia, el temporizador desaparece. Para tareas durables, utiliza systemd timers, cron, una cola de trabajos o un planificador respaldado por almacenamiento.

Cuándo utilizar timerfd

Es una excelente opción para daemons Linux, proxies, recolectores, simuladores y servicios que ya usan descriptores. En scripts pequeños, time.sleep() suele ser más legible. Para código asíncrono portable, consulta asyncio en Python. Para medir tiempos con precisión, revisa perf_counter_ns en Python. También son útiles datetime en Python y zoneinfo para zonas horarias.

La documentación oficial del módulo os describe la API disponible. La página de manual timerfd_create(2) explica el comportamiento del kernel.

Conclusión

os.timerfd_create conecta Python con el modelo de eventos basado en descriptores de Linux. Ofrece plazos precisos, integración natural con poll y un contador que permite detectar procesamiento atrasado. Una implementación sólida verifica compatibilidad, prefiere el reloj monotónico para duraciones, usa flags seguras, interpreta correctamente los ocho bytes y cierra el descriptor en todos los caminos de salida. Con estas prácticas, timerfd se convierte en una pieza muy eficiente para software de infraestructura y automatización.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Depuración de un proceso Python en terminal con código
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depura procesos Python en ejecución

    Aprende a conectar pdb a un proceso Python en ejecución, inspeccionar la pila y diagnosticar bloqueos de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026
    Código Python para representar fracciones exactas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    fractions.from_number: convierte números en fracciones

    Aprende fractions.from_number en Python para convertir números en fracciones exactas, controlar precisión, validar entradas y evitar redondeos inesperados.

    Ler mais

    Tempo de leitura: 4 minutos
    09/10/2026
    Desarrollador configurando un servidor HTTPS y certificado TLS con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crea un servidor HTTPS local en Python

    Aprende HTTPSServer en Python para crear servicios HTTPS locales, configurar certificados, usar hilos y comprender sus límites.

    Ler mais

    Tempo de leitura: 4 minutos
    08/10/2026
    Archivos protegidos que representan extracción segura de TAR con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extrae TAR con seguridad

    Aprende tarfile extraction_filter en Python para extraer archivos TAR con validación, seguridad y control de rutas.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026
    Código Python mostrando avisos controlados con catch_warnings
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: captura warnings en pruebas Python

    Aprende catch_warnings en Python para capturar, probar y controlar avisos con filtros específicos y alcance seguro.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python que representa referencias persistentes de pickle
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serializa referencias externas

    Aprende pickle persistent_id en Python para referencias externas estables, validación, seguridad, rendimiento y compatibilidad.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026