timerfd is a timer interface provided by Linux for user programs. The interface is based on file descriptors, and can be used for epoll/select through time-out notification through readable events of file descriptors. There are three main functions.
Header file: include < sys / timerfd. H >
int timerfd_create(int clockid, int flags)
Function: generate timer and return file descriptor.
clockid: CLOCK_ Mononic or CLOCK_REALTIME, where CLOCK_MONOTONIC indicates that the acquired time is the time from the system restart to the present, and changing the system time has no impact on it. CLOCK_REALTIME indicates the time from January 1, 1970 to the current time. Changing the system time will change the obtained value.
flags: TFD_ Nonblock, TFD_ Cloexec (same as O_CLOEXEC).
return: file descriptor of timer.
int timerfd_settime(int tfd, int flags, const struct itimerspec *newValue, struct itimerspec *oldValue)
Function: used to start or close the specified fd timer.
tfd: timerfd, by timerfd_ The create function returns.
flags: 1 indicates that the absolute time is set; 0 indicates relative time.
newValue: specify a new timeout, if newValue.it_ If value is not 0, start the timer, otherwise close the timer. If newValue.it_ If interval is 0, the timer is timed only once, otherwise it will timeout every set time.
oldValue: if it is not NULL, the timeout time before the timer is set this time is returned.
return: returns - 1 if failed.
struct timespec
{
time_t tv_sec; // second
long tv_nsec; // nanosecond
}
struct itimerspec
{
struct timespec it_interval; // Every it after the first timeout_ Interval timeout once
struct timespec it_value; // First timeout
}
int timerfd_gettime(int fd, struct itimerspec *curValue)
Function: used to obtain the time left until the next timeout. If the timer has expired (i.e. it_value time is exceeded) and the timer is in circular mode (i.e. it_interval is not 0), the timer starts timing again after calling this function.
fd: timerfd, by timerfd_ The create function returns.
curValue: returns the time remaining until the next timeout.
return: return - 1 if failed
Read timerfd
When the timer times out, the timerfd is readable and returns Uint64_ An integer of type T, which is the number of timeouts (the number of timeouts unread). If the timer does not have a timeout event, if timerfd is blocked, read will be blocked. If timerfd is non blocked, EAGAIN error will be returned. If the read yes data is less than 8 bytes, an EINVAL error is returned.
Sample code
#include <sys/timerfd.h> #include <sys/epoll.h> #include <unistd.h> #include <stdint.h> #include <iostream> using namespace std; const int EPOLL_SIZE = 10; int main(int argc, char* argv[]) { int tfd, epfd, nfds; struct epoll_event event; struct epoll_event events[EPOLL_SIZE]; //Create timerfd, CLOCK_REALTIME is absolute time, TFD_NONBLOCK is non blocking tfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); if (tfd < 0) { cerr << "timerfd_create error!" << endl; return -1; } struct timespec startTime, intervalTime; startTime.tv_sec = 0; startTime.tv_nsec = 1; //Equivalent to immediate arrival timeout intervalTime.tv_sec = 3; //After the first timeout, timeout every three seconds intervalTime.tv_nsec = 0; struct itimerspec newValue; newValue.it_value = startTime; newValue.it_interval = intervalTime; //Set the timeout, which is a relative time if (timerfd_settime(tfd, 0, &newValue, NULL) < 0) { cerr << "timerfd_settime error!" << endl; return -1; } //Use epoll to listen for descriptors epfd = epoll_create(EPOLL_SIZE); if (epfd < 0) { cerr << "epoll_create error!" << endl; return -1; } event.data.fd = tfd; event.events = EPOLLIN; if (epoll_ctl(epfd, EPOLL_CTL_ADD, tfd, &event) < 0) { cerr << "epoll_ctl error!" << endl; return -1; } uint64_t count = 0; while (1) { //Non blocking wait nfds = epoll_wait(epfd, events, EPOLL_SIZE, 0); if (nfds == 0) continue; for (int i = 0; i < nfds; i++) { if (events[i].events & EPOLLIN) { uint64_t data; read(events[i].data.fd, &data, sizeof(uint64_t)); count += data; cout << "read: " << data << ", timer count: " << count << endl; } } } return 0; }