插件窝 干货文章 linux定时器实现的方法是什么

linux定时器实现的方法是什么

Timer 定时器 示例 内核 746    来源:    2025-05-15

在 Linux 系统中,定时器的实现方法有多种,具体选择取决于应用场景和精度要求。以下是常见的实现方式及其详细说明:


1. sleep()usleep()

  • 用途:简单的延迟执行。
  • 特点:精度较低(秒级或微秒级),会阻塞当前线程。
  • 示例c sleep(5); // 阻塞5秒 usleep(500000); // 阻塞500毫秒

2. alarm() 和信号(SIGALRM)

  • 用途:基于信号的定时器,适合单次或简单重复任务。
  • 特点:秒级精度,通过信号处理器(signal handler)触发。
  • 示例: ```c #include <signal.h> #include <unistd.h>

    void handler(int sig) { printf("Timer expired!\n"); }

    int main() { signal(SIGALRM, handler); alarm(5); // 5秒后触发SIGALRM while(1) pause(); // 等待信号 } ```


3. setitimer()

  • 用途:比 alarm() 更精确的周期性定时器(微秒级)。
  • 模式:支持 ITIMER_REAL(真实时间)、ITIMER_VIRTUAL(进程用户态时间)等。
  • 示例: ```c #include <sys/time.h>

    void handler(int sig) { printf("Timer triggered.\n"); }

    int main() { struct itimerval timer; signal(SIGALRM, handler);

     timer.it_value.tv_sec = 1;     // 首次触发延迟1秒
     timer.it_value.tv_usec = 0;
     timer.it_interval.tv_sec = 1;  // 后续间隔1秒
     timer.it_interval.tv_usec = 0;
    
     setitimer(ITIMER_REAL, &timer, NULL);
     while(1) pause();
    

    } ```


4. POSIX 定时器(timer_create()

  • 用途:高精度定时器(纳秒级),支持多线程和灵活的信号或线程通知。
  • 通知方式:可通过信号(SIGEV_SIGNAL)或线程回调(SIGEV_THREAD)。
  • 示例(信号通知): ```c #include <time.h> #include <signal.h>

    void handler(int sig, siginfo_t *si, void *uc) { printf("POSIX timer fired.\n"); }

    int main() { timer_t timerid; struct sigevent sev; struct itimerspec its;

     // 设置信号处理
     struct sigaction sa;
     sa.sa_flags = SA_SIGINFO;
     sa.sa_sigaction = handler;
     sigaction(SIGRTMIN, &sa, NULL);
    
     // 配置定时器事件
     sev.sigev_notify = SIGEV_SIGNAL;
     sev.sigev_signo = SIGRTMIN;
     sev.sigev_value.sival_ptr = &timerid;
     timer_create(CLOCK_REALTIME, &sev, &timerid);
    
     // 设置首次1秒触发,之后每0.5秒一次
     its.it_value.tv_sec = 1;
     its.it_value.tv_nsec = 0;
     its.it_interval.tv_sec = 0;
     its.it_interval.tv_nsec = 500000000;
     timer_settime(timerid, 0, &its, NULL);
    
     while(1) pause();
    

    } ```


5. epoll/select 超时机制

  • 用途:结合 I/O 多路复用实现定时回调,适合网络应用。
  • 特点:毫秒级精度,非阻塞。
  • 示例: ```c #include <sys/epoll.h>

    int main() { int epfd = epoll_create1(0); struct epoll_event ev; int timeout_ms = 5000; // 5秒超时

     while(1) {
         int n = epoll_wait(epfd, &ev, 1, timeout_ms);
         if (n == 0) {
             printf("Timeout occurred!\n");
         }
     }
    

    } ```


6. 内核模块定时器(add_timer()

  • 用途:内核开发中使用的动态定时器。
  • 特点:基于 jiffies(内核时间单位),精度依赖内核配置。
  • 示例(内核模块): ```c #include <linux/timer.h>

    static struct timer_list my_timer;

    void timer_callback(struct timer_list *t) { printk("Kernel timer expired!\n"); mod_timer(&my_timer, jiffies + msecs_to_jiffies(2000)); // 重新设置2秒后触发 }

    static int __init my_init(void) { timer_setup(&my_timer, timer_callback, 0); mod_timer(&my_timer, jiffies + msecs_to_jiffies(2000)); return 0; } ```


7. 用户态定时器库(如 libuvBoost.Asio

  • 用途:跨平台的高性能定时器,常用于事件驱动框架。
  • 示例(libuv): ```c #include <uv.h>

    void callback(uv_timer_t *handle) { printf("Libuv timer callback.\n"); }

    int main() { uv_loop_t *loop = uv_default_loop(); uv_timer_t timer; uv_timer_init(loop, &timer); uv_timer_start(&timer, callback, 1000, 2000); // 首次1秒后触发,之后每2秒一次 uv_run(loop, UV_RUN_DEFAULT); } ```


选择建议

  • 简单延迟:用 sleepusleep
  • 周期性任务setitimer 或 POSIX 定时器。
  • 高精度需求:POSIX 定时器(timer_create)。
  • 内核开发:内核定时器 API。
  • 非阻塞事件循环epoll 或异步库(如 libuv)。

根据具体场景选择合适的方法,并注意信号安全性和线程兼容性。