510 Chapter 23
the maximum number of expirations of the timer that the program should wait for
before terminating; the default for this argument is 1.
The program creates a timer using timerfd_create(), and arms it using
timerfd_settime(). It then loops, reading expiration notifications from the file
descriptor until the specified number of expirations has been reached. After each
read(), the program displays the time elapsed since the timer was started, the num-
ber of expirations read, and the total number of expirations so far.
In the following shell session log, the command-line arguments specify a timer
with a 1-second initial value and 1-second interval, and a maximum of 100 expirations.
$ ./demo_timerfd 1:1 100
1.000: expirations read: 1; total=1
2.000: expirations read: 1; total=2
3.000: expirations read: 1; total=3
Type Control-Z to suspend program in background for a few seconds
[1]+ Stopped ./demo_timerfd 1:1 100
$ fg Resume program in foreground
./demo_timerfd 1:1 100
14.205: expirations read: 11; total=14 Multiple expirations since last read()
15.000: expirations read: 1; total=15
16.000: expirations read: 1; total=16
Type Control-C to terminate the program
From the above output, we can see that multiple timer expirations occurred while
the program was suspended in the background, and all of these expirations were
returned on the first read() after the program resumed execution.
Listing 23-8: Using the timerfd API
––––––––––––––––––––––––––––––––––––––––––––––––––––– timers/demo_timerfd.c
#include <sys/timerfd.h>
#include <time.h>
#include <stdint.h> /* Definition of uint64_t */
#include "itimerspec_from_str.h" /* Declares itimerspecFromStr() */
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
struct itimerspec ts;
struct timespec start, now;
int maxExp, fd, secs, nanosecs;
uint64_t numExp, totalExp;
ssize_t s;
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s secs[/nsecs][:int-secs[/int-nsecs]] [max-exp]\n", argv[0]);
itimerspecFromStr(argv[1], &ts);
maxExp = (argc > 2)? getInt(argv[2], GN_GT_0, "max-exp") : 1;