Linux timerfd, calling a function every x seconds without blocking code execution

You need to call the function every X (say, 5) seconds, and the code below. But its blocking code execution. Since I want it to work as setitimer, where I can say that you call the function every 5 seconds and do something else. Thanks

#include <sys/timerfd.h> #include <time.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <stdint.h> /* Definition of uint64_t */ #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { struct itimerspec new_value; int max_exp, fd; struct timespec now; uint64_t exp, tot_exp; ssize_t s; if (clock_gettime(CLOCK_REALTIME, &now) == -1) handle_error("clock_gettime"); /* Create a CLOCK_REALTIME absolute timer with initial expiration and interval as specified in command line */ new_value.it_value.tv_sec = now.tv_sec + 1; new_value.it_value.tv_nsec = now.tv_nsec; new_value.it_interval.tv_sec = 5; new_value.it_interval.tv_nsec = 0; max_exp = 5; //say 5 times fd = timerfd_create(CLOCK_REALTIME, 0); if (fd == -1) handle_error("timerfd_create"); if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1) handle_error("timerfd_settime"); printf("timer started\n"); for (tot_exp = 0; tot_exp < max_exp;) { s = read(fd, &exp, sizeof(uint64_t)); if (s != sizeof(uint64_t)) handle_error("read"); tot_exp += exp; printf("read: %llu; total=%llu\n", (unsigned long long) exp, (unsigned long long) tot_exp); } //Do something else ? //while(1); exit(EXIT_SUCCESS); } 

EDIT I have one more question. When changing these lines in the above code from

  new_value.it_interval.tv_sec = 5; new_value.it_interval.tv_nsec = 0; 

to

  new_value.it_interval.tv_sec = 0; new_value.it_interval.tv_nsec = 5000000000; 

I see that there is no 5 second delay What is happening here?

+4
source share
2 answers

You need to understand how to use multiplexed system calls, such as polling (2) (or an older select(2) , which is usually deprecated) and use them to verify the readability of the file descriptor received by timerfd_create (2) before read(2) -in it.

However, remember that timerfd_create only works when the read call succeeds. Therefore, only when poll tells you that fd is not readable can you do something else. Something else should be fast (last less than 5 seconds).

You might want to explore event loop libraries, such as libevent (wrapping poll ). If you code a graphical application (using Qt or Gtk), it already has its own event loop. If you are smart enough, you can make your 5 second period without any timerfd_create , only through your event loop (by carefully setting the timeout specified on poll , etc.).

Additions:

the tv_nsec field tv_nsec always be non-negative and less than 1,000,000,000 (number of seconds per second).

+2
source

Why should you use timerfd? Just set an alarm and make a handler for SIGALRM to call your function.

If you do not want to use signals, just create an additional thread to block on your fd timer and continue as usual in the main thread.

If you do not like any of them, and you want to work while you wait, you need to interview. You can do this as basile suggests, or simply save the current time and check when you will be polling to see if the desired period has expired.

0
source

Source: https://habr.com/ru/post/1435102/


All Articles