在用C++实现一个定时任务框架文章中实现了一个定时任务的框架,本文将将继续针对定时任务进行介绍帮助大家根据具体的应用场景选择合适的方式。
Linux开发环境下们可以将一个基于时间的文件描述符注册到epoll实例,定时器到期时就可以通过epoll接收事件,这种方法在技术事件驱动的应用程序中一种常见的模式,尤其是需要处理多I/O事件的服务程序。如下面的示例:
#define MAX_EVENTS 5
int main() {
int timer_fd = timerfd_create(CLOCK_REALTIME, 0);
if (timer_fd == -1) {
perror("timerfd_create");
return 1;
}
struct itimerspec new_value;
memset(&new_value, 0, sizeof(new_value));
/*
it_value 代表定时器第一次到期的时间。这里设置
为5秒后,意味着定时器将在5秒后第一次触发
*/
new_value.it_value.tv_sec = 5;
/*
it_interval 设置定时器的重复周期。此处同样设置为每5秒触发一次
如果设置为0,则定时器只会触发一次
*/
new_value.it_interval.tv_sec = 5;
if (timerfd_settime(timer_fd, 0, &new_value, NULL) == -1) {
perror("timerfd_settime");
return 1;
}
int epoll_fd = epoll_create1(0);
if (epoll_fd == -1) {
perror("epoll_create1");
return 1;
}
struct epoll_event event;
memset(&event, 0, sizeof(event));
/*
EPOLLIN 指定了需要监听的事件类型,此处为“可读”事件,
对于定时器而言,到期即视为可读
*/
event.events = EPOLLIN;
/*
event.data.fd 设置为 timer_fd,意味着这是我们希望 epoll
监视的文件描述符
*/
event.data.fd = timer_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &event) == -1) {
perror("epoll_ctl");
return 1;
}
struct epoll_event events[MAX_EVENTS];
while (1) {
/*
epoll_wait 函数等待注册在 epoll 实例 epoll_fd 上的事件,
这个实例需要事先通过 epoll_create 和 epoll_ctl 配置。
events 是一个数组,用于接收发生的事件。
MAX_EVENTS 定义了 events 数组可以接收的最大事件数量。
-1 表示 epoll_wait 会无限期等待,直到至少有一个事件发生。
*/
int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
for (int i = 0; i < n; i++) {
if (events[i].data.fd == timer_fd) {
uint64_t expirations;
read(timer_fd, &expirations, sizeof(expirations));
printf("Timer expired %lu times\n", expirations);
}
}
}
close(timer_fd);
close(epoll_fd);
return 0;
}
Linux环境下,还可以使用timerfd来触发定时任务。timerfd是Linux提供的一个文件描述符,可以用来实现定时任务的触发。如代码所示:
// 获取并打印当前系统时间
void printCurrentTime() {
time_t now = time(0);
struct tm tstruct;
char buf[80];
tstruct = *localtime(&now);
strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
std::cout << "Current System Time: " << buf << std::endl;
}
int main() {
// 创建 timerfd
int timer_fd = timerfd_create(CLOCK_REALTIME, 0);
if (timer_fd == -1) {
std::cerr << "Failed to create timerfd: " << strerror(errno) << std::endl;
return 1;
}
// 设置定时器参数
struct itimerspec timer_spec;
timer_spec.it_interval.tv_sec = 5; // 每5秒触发一次
timer_spec.it_interval.tv_nsec = 0;
timer_spec.it_value.tv_sec = 5; // 初始延迟5秒触发
timer_spec.it_value.tv_nsec = 0;
// 启动定时器
if (timerfd_settime(timer_fd, 0, &timer_spec, NULL) == -1) {
std::cerr << "Failed to set timerfd: " << strerror(errno) << std::endl;
close(timer_fd);
return 1;
}
// 读取定时器事件
uint64_t num_exp;
ssize_t read_bytes;
while (true) {
read_bytes = read(timer_fd, &num_exp, sizeof(num_exp));
if (read_bytes != sizeof(num_exp)) {
std::cerr << "Error reading timerfd: " << strerror(errno) << std::endl;
break;
}
// 每次定时器触发时执行的任务
printCurrentTime();
}
// 关闭 timerfd
close(timer_fd);
return 0;
}
参考链接: https://blog.csdn.net/weixin_44046545/article/details/138232447