插件窝 干货文章 linux怎么实现定时器

linux怎么实现定时器

定时器 timer timerfd include 606    来源:    2025-04-06

Linux定时器实现方法

在Linux系统中,有多种方式可以实现定时器功能,以下是几种常用的方法:

1. sleep系列函数

#include <unistd.h>

// 秒级休眠
sleep(seconds);

// 微秒级休眠
usleep(microseconds);

// 纳秒级休眠
nanosleep(&ts, NULL);  // ts是timespec结构体

2. alarm信号

#include <unistd.h>
#include <signal.h>

void alarm_handler(int sig) {
    // 定时器触发时的处理
}

int main() {
    signal(SIGALRM, alarm_handler);
    alarm(5);  // 5秒后触发SIGALRM信号
    while(1) pause();
    return 0;
}

3. setitimer定时器

更精确的定时器,支持三种模式: - ITIMER_REAL: 真实时间 - ITIMER_VIRTUAL: 进程用户态CPU时间 - ITIMER_PROF: 进程用户态和内核态CPU时间

#include <sys/time.h>

void timer_handler(int sig) {
    // 定时器处理
}

int main() {
    struct itimerval timer;

    signal(SIGALRM, timer_handler);

    // 首次触发时间
    timer.it_value.tv_sec = 1;
    timer.it_value.tv_usec = 0;

    // 间隔时间
    timer.it_interval.tv_sec = 1;
    timer.it_interval.tv_usec = 0;

    setitimer(ITIMER_REAL, &timer, NULL);

    while(1);
    return 0;
}

4. POSIX定时器 (timer_create)

更现代、更灵活的定时器接口:

#include <signal.h>
#include <time.h>

void timer_handler(union sigval sv) {
    // 定时器处理
}

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

    sev.sigev_notify = SIGEV_THREAD;
    sev.sigev_notify_function = timer_handler;
    sev.sigev_value.sival_ptr = &timerid;

    timer_create(CLOCK_REALTIME, &sev, &timerid);

    its.it_value.tv_sec = 1;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = 1;
    its.it_interval.tv_nsec = 0;

    timer_settime(timerid, 0, &its, NULL);

    while(1);
    return 0;
}

5. 使用epoll/poll/select实现定时器

#include <sys/epoll.h>
#include <sys/timerfd.h>

int main() {
    int epollfd = epoll_create1(0);
    int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);

    struct itimerspec its;
    its.it_value.tv_sec = 1;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = 1;
    its.it_interval.tv_nsec = 0;
    timerfd_settime(timerfd, 0, &its, NULL);

    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = timerfd;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev);

    while(1) {
        int n = epoll_wait(epollfd, &ev, 1, -1);
        if (ev.data.fd == timerfd) {
            uint64_t exp;
            read(timerfd, &exp, sizeof(exp));
            // 定时器触发处理
        }
    }
    return 0;
}

6. 使用crontab命令(系统级定时任务)

# 编辑crontab
crontab -e

# 添加定时任务,例如每天凌晨1点执行
0 1 * * * /path/to/your/script.sh

7. 使用at命令(一次性定时任务)

# 明天10点执行命令
echo "command" | at 10:00 tomorrow

选择建议

  • 简单延迟:使用sleep/usleep
  • 简单定时任务:使用alarm
  • 需要精确控制:使用setitimer或POSIX定时器
  • 需要与I/O复用结合:使用timerfd+epoll
  • 系统级定时任务:使用crontab或at

根据你的具体需求选择合适的定时器实现方式。