таймер и читать

У меня есть приложение, которое периодически (по таймеру) проверяет некоторые данные хранения.
Как это:

#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/fcntl.h>
#include <unistd.h>

// EPOLL & TIMER
#include <sys/epoll.h>
#include <sys/timerfd.h>

int main(int argc, char **argv)
{
/* epoll instance */
int efd = epoll_create1(EPOLL_CLOEXEC);

if (efd < 0)
{
std::cerr << "epoll_create error: " << strerror(errno) << std::endl;
return EXIT_FAILURE;
}

struct epoll_event ev;
struct epoll_event events[128];

/* timer instance */
int tfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);

struct timespec ts;
// first expiration in 3. seconds after program start
ts.tv_sec = 3;
ts.tv_nsec = 0;

struct itimerspec new_timeout;
struct itimerspec old_timeout;

bzero(&new_timeout, sizeof(new_timeout));
bzero(&old_timeout, sizeof(old_timeout));

// value
new_timeout.it_value = ts;

// no interval;
// timer will be armed in epoll_wait event trigger
new_timeout.it_interval.tv_sec =
new_timeout.it_interval.tv_nsec = 0;

// Add the timer descriptor to epoll.
if (tfd != -1)
{
ev.events = EPOLLIN | EPOLLERR /*| EPOLLET*/;
ev.data.ptr = &tfd;
epoll_ctl(efd, EPOLL_CTL_ADD, tfd, &ev);
}

int flags = 0;
if (timerfd_settime(tfd, flags, &new_timeout, &old_timeout) < 0)
{
std::cerr << "timerfd_settime error: " << strerror(errno) << std::endl;
}

int numEvents = 0;
int timeout = 0;
bool checkTimer = false;
while (1)
{
checkTimer = false;
numEvents = epoll_wait(efd, events, 128, timeout);
if (numEvents > 0)
{
for (int i = 0; i < numEvents; ++i)
{
if (events[i].data.ptr == &tfd)
{
std::cout << "timeout" << std::endl;
checkTimer = true;
}
}
}
else if(numEvents == 0)
{
continue;
}
else
{
std::cerr << "An error occured: " << strerror(errno) << std::endl;
}

if (checkTimer)
{
/* Check data storage */
uint64_t value;
ssize_t readBytes;
//while ( (readBytes = read(tfd, &value, 8)) > 0)
//{
//    std::cout << "\tread: '" << value << "'" << std::endl;
//}
itimerspec new_timeout;
itimerspec old_timeout;
new_timeout.it_value.tv_sec = rand() % 3 + 1;
new_timeout.it_value.tv_nsec = 0;
new_timeout.it_interval.tv_sec =
new_timeout.it_interval.tv_nsec = 0;
timerfd_settime(tfd, flags, &new_timeout, &old_timeout);
}
}

return EXIT_SUCCESS;
}

Это простое описание моего приложения.
После каждого таймаута таймер должен быть изменен на некоторое значение, отличающееся в каждом тайм-ауте.

Вопросы:

  1. Нужно ли добавлять timerfd в epoll (epoll_ctl) с флагом EPOLLET?
  2. Нужно ли читать timerfd после каждого тайм-аута?
  3. Нужно ли epoll_wait бесконечно (время ожидания = -1)?

3

Решение

Вы можете сделать это в одном из двух режимов: по краю или по уровню. Если вы выберете маршрут по краю, то вы должны пройти EPOLLET и не нужно читать timerfd после каждого пробуждения. Тот факт, что вы получаете событие от epoll означает, что один или несколько тайм-аутов сработали. При желании вы можете прочитать timerfd и он вернет количество тайм-аутов, которые сработали с тех пор как вы в последний раз читали это.

Если вы выбираете трассу, запускаемую уровнем, вам не нужно проходить EPOLLET, но ты должен читать timerfd после каждого пробуждения. Если вы этого не сделаете, вы сразу же проснетесь снова, пока не потратите время.

Вы должны либо пройти -1 в epoll как время ожидания или какое-то положительное значение. Если вы пройдете 0Как и в примере, вы никогда не заснете, а просто закружитесь, ожидая времени, которое сработает. Это почти наверняка нежелательное поведение.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]