You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Linux中创建微秒级定时器间隔?以及C/C++实现精确50usec中断式定时器的标准方法咨询

Answers to Your Linux Timer Questions

1. Creating Microsecond-Level Timer Intervals in Linux

Great question—microsecond-level timing on Linux depends a lot on whether you're working in user space or kernel space, and how strict your precision needs are. Here are the most reliable approaches:

User-Space Methods

  • timerfd (POSIX Standard, Preferred)
    This is the modern, file-descriptor-based timer interface that plays nicely with epoll or select, making it easy to slot into event-driven apps. It supports microsecond precision as long as your kernel has high-resolution timers enabled (most modern distros have this turned on by default).

    Example C code snippet:

    #include <sys/timerfd.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdint.h>
    
    int main() {
        int timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
        if (timer_fd == -1) {
            perror("timerfd_create");
            return 1;
        }
    
        struct itimerspec timer_spec;
        // Fire immediately on start
        timer_spec.it_value.tv_sec = 0;
        timer_spec.it_value.tv_nsec = 1;
        // Set interval to 50 microseconds (50,000 nanoseconds)
        timer_spec.it_interval.tv_sec = 0;
        timer_spec.it_interval.tv_nsec = 50 * 1000;
    
        if (timerfd_settime(timer_fd, 0, &timer_spec, NULL) == -1) {
            perror("timerfd_settime");
            close(timer_fd);
            return 1;
        }
    
        uint64_t expirations;
        while (1) {
            ssize_t bytes_read = read(timer_fd, &expirations, sizeof(expirations));
            if (bytes_read == sizeof(expirations)) {
                printf("Timer fired %llu times\n", (unsigned long long)expirations);
                // Your 50us interval logic goes here
            }
        }
    
        close(timer_fd);
        return 0;
    }
    
  • setitimer (Legacy POSIX)
    An older interface that sends signals (like SIGALRM) when the timer expires. Keep in mind that signal delivery can have noticeable jitter due to kernel scheduling, so it's less reliable for strict microsecond timing compared to timerfd.

Kernel-Space Methods

If you need rock-solid, interrupt-level precision (e.g., for hardware control), you'll need to write a kernel module using the kernel's hrtimer API, which supports nanosecond-level granularity directly in the kernel.

2. Standard Method for a Precise 50usec Interrupt-Based Timer in C/C++ on Linux

First, a quick clarification: true hardware interrupts are kernel-only—user-space code can't directly register interrupt handlers. But we can get extremely close to interrupt-like behavior (low jitter, periodic execution) using kernel-assisted timers, and there are standard POSIX tools to make this happen.

Combine timerfd with real-time scheduling to minimize jitter:

  1. Verify high-resolution timers are enabled (check /sys/devices/system/clocksource/clocksource0/current_clocksource—it should show something like tsc or hpet).
  2. Set your process to use a real-time scheduling policy (e.g., SCHED_FIFO) to avoid being preempted by lower-priority tasks.

Add this snippet to the timerfd example above to enable real-time scheduling:

#include <sched.h>

int main() {
    struct sched_param param;
    param.sched_priority = sched_get_priority_max(SCHED_FIFO);
    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
        perror("sched_setscheduler");
        // Note: You'll need root privileges for this
    }

    // Rest of the timerfd code...
}

Kernel-Space "True Interrupt" Timer

If you need actual interrupt-level execution (e.g., for controlling hardware with minimal latency), here's a minimal kernel module skeleton using hrtimer:

#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>

static struct hrtimer timer;

enum hrtimer_restart timer_callback(struct hrtimer *hr_timer) {
    // Keep this code SHORT—kernel callbacks can't block!
    ktime_t now = hrtimer_cb_get_time(hr_timer);
    hrtimer_forward_now(hr_timer, ns_to_ktime(50 * 1000)); // 50us interval
    return HRTIMER_RESTART;
}

static int __init timer_init(void) {
    ktime_t interval = ns_to_ktime(50 * 1000);
    hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    timer.function = timer_callback;
    hrtimer_start(&timer, interval, HRTIMER_MODE_REL);
    return 0;
}

static void __exit timer_exit(void) {
    hrtimer_cancel(&timer);
}

module_init(timer_init);
module_exit(timer_exit);
MODULE_LICENSE("GPL");

Key Precision Tips

  • Always use CLOCK_MONOTONIC instead of CLOCK_REALTIME—it's not affected by system clock changes (like NTP updates).
  • For user-space code, run as root to access real-time scheduling privileges.
  • Kernel timer callbacks must be extremely brief—long code will block the kernel and cause system instability.

内容的提问来源于stack exchange,提问作者Dimpu10

火山引擎 最新活动