timer_create
和
timer_settime
函数来创建和设置定时器。
在Linux系统中,C语言实现定时器功能主要有以下几种方式:
1、setitimer()函数
原理:通过设置struct itimerval
结构体来指定定时器的初始启动时间和间隔时间,然后调用setitimer()
函数启动定时器,当定时器超时或到达间隔时间时,会向进程发送SIGALRM信号。
示例代码
#include <stdio.h> #include <string.h> #include <signal.h> #include <sys/time.h> #include <unistd.h> void sig_alm_handler(int sig_num) { printf("Received SIGALRM signal, timer expired! "); } int main() { signal(SIGALRM, sig_alm_handler); // 注册SIGALRM信号的处理方法 struct itimerval mytimer; mytimer.it_value.tv_sec = 5; // 初始启动时间为5秒后 mytimer.it_value.tv_usec = 0; mytimer.it_interval.tv_sec = 3; // 间隔时间为3秒 mytimer.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &mytimer, NULL); // 启动定时器 while (1) { pause(); // 等待信号到来 } return 0; }
优缺点:优点是可以实现微妙级定时;缺点是定时器是一次性的,需要手动重启以实现循环定时。
2、alarm()函数
原理:设置一个一次性定时器,当定时时间到达时,会向进程发送SIGALRM信号。
示例代码
#include <stdio.h> #include <unistd.h> #include <signal.h> void sig_alm_handler(int sig_num) { printf("Received SIGALRM signal, timer expired! "); } int main() { signal(SIGALRM, sig_alm_handler); // 注册SIGALRM信号的处理方法 alarm(5); // 设置定时时间为5秒后 while (1) { pause(); // 等待信号到来 } return 0; }
优缺点:优点是使用简单;缺点是只能实现一次性定时,且精度相对较低。
3、timerfd_create()系统调用
原理:创建一个新的计时器文件描述符,可以通过对该文件描述符的操作来控制定时器的行为,如设置超时时间和间隔时间等,当定时器超时时,可以通过读取该文件描述符来获取通知。
示例代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/timerfd.h> #include <time.h> #include <stdint.h> #include <string.h> int main() { int fd = timerfd_create(CLOCK_REALTIME, 0); // 创建定时器文件描述符 if (fd == -1) { perror("timerfd_create"); return 1; } struct itimerspec new_time; memset(&new_time, 0, sizeof(new_time)); new_time.it_value.tv_sec = 5; // 初始启动时间为5秒后 new_time.it_value.tv_nsec = 0; new_time.it_interval.tv_sec = 3; // 间隔时间为3秒 new_time.it_interval.tv_nsec = 0; if (timerfd_settime(fd, 0, &new_time, NULL) == -1) { perror("timerfd_settime"); return 1; } uint64_t exp; while (1) { ssize_t s = read(fd, &exp, sizeof(uint64_t)); // 读取定时器文件描述符获取通知 if (s != sizeof(uint64_t)) { perror("read"); return 1; } printf("Timer expired, count: %lu ", exp); } return 0; }
优缺点:优点是功能强大,可以精确地控制定时器的行为;缺点是相对较复杂,需要对文件描述符进行操作。
1、如何选择合适的定时器函数?
如果需要高精度的定时,可以选择timerfd_create()
系统调用;如果只是简单地实现一个基本的定时功能,alarm()
函数可能就足够了;如果需要更灵活的定时控制,如循环定时和微妙级定时,setitimer()
函数是一个不错的选择,具体选择取决于应用的需求和场景。
2、如何处理多个定时器同时触发的情况?
可以使用多线程或异步编程的方式来处理多个定时器同时触发的情况,为每个定时器创建一个单独的线程或使用异步信号处理机制来处理不同的定时器回调函数,需要注意线程同步和数据竞争等问题,以确保程序的正确性和稳定性。