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

    Entorno de desarrollo con varias pantallas que representa threads y el GIL en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    sys._is_gil_enabled: comprueba si el GIL está activo

    Aprende a detectar si el GIL está activo en Python y adapta concurrencia, pruebas, métricas y compatibilidad con builds free-threaded.

    Ler mais

    Tempo de leitura: 5 minutos
    27/09/2026
    Terminal en un portátil representando cambios temporales de directorio con contextlib.chdir
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    contextlib.chdir: cambia directorios temporalmente

    Aprende contextlib.chdir en Python para cambiar directorios temporalmente con seguridad en scripts, pruebas, builds y automatizaciones.

    Ler mais

    Tempo de leitura: 5 minutos
    26/09/2026
    Desarrolladora usando intérpretes aislados de Python en un entorno de servidores
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    concurrent.interpreters: paralelismo aislado en Python

    Aprende concurrent.interpreters en Python para usar intérpretes aislados, tareas paralelas, colas, compatibilidad y cierre seguro.

    Ler mais

    Tempo de leitura: 7 minutos
    26/09/2026
    Desarrollador usando Python para inspeccionar archivos con pathlib.Path.info
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pathlib.Path.info: inspecciona archivos con eficiencia

    Aprende pathlib.Path.info en Python para inspeccionar archivos y directorios con eficiencia.

    Ler mais

    Tempo de leitura: 7 minutos
    25/09/2026
    Estructura de archivos y código para os.path.splitroot en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    os.path.splitroot: separa unidad, raíz y ruta

    Aprende os.path.splitroot en Python para separar unidad, raíz y resto de rutas Windows, POSIX y UNC con seguridad.

    Ler mais

    Tempo de leitura: 4 minutos
    25/09/2026
    Código y estructura de archivos para filtros con glob.translate en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    glob.translate: convierte patrones glob a regex

    Aprende glob.translate en Python para convertir patrones glob en regex y filtrar rutas con recursión, separadores y seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    24/09/2026