What kind of timer?
Having created the timer, you now have to decide what kind of timer it is. This is done by a combination of arguments to timer_settime(), the function used to start the timer.
#include <time.h>
int
timer_settime (timer_t timerid,
int flags,
struct itimerspec *value,
struct itimerspec *oldvalue);
The flags argument is where you specify absolute versus relative.
If you pass the constant TIMER_ABSTIME, then it's absolute, pretty much as you'd expect. You then pass the actual date and time when you want the timer to go off.
If you pass a zero, then the timer is considered relative to the current time.
Let's look at how you specify the times. Here are key portions of two data structures (in <time.h>):
struct timespec {
long tv_sec,
tv_nsec;
};
struct itimerspec {
struct timespec it_value,
it_interval;
};
There are two members in struct itimerspec:
- it_value
- the one-shot value
- it_interval
- the reload value
The it_value specifies either how long from now the timer should go off
(for a relative timer), or when the timer should go off (for an absolute timer).
Once the timer fires, the it_interval value specifies a relative value to reload
the timer with so that it can trigger again.
Note that specifying a value of zero for the it_interval makes it into a one-shot
timer.
You might expect that to create a pure
periodic timer; you'd just set the
it_interval to the reload value, and set it_value to zero.
Unfortunately, the last part of that statement is false—setting it_value to
zero disables the timer.
If you want to create a pure periodic timer, set it_value equal to
it_interval and create the timer as a relative timer.
This will fire once (for the it_value delay) and then keep reloading with the
it_interval delay.
Both the it_value and it_interval members are actually structures of type struct timespec, another POSIX thing. The structure lets you specify sub-second resolutions. The first member, tv_sec, is the number of seconds; the second member, tv_nsec, is the number of nanoseconds in the current second. (What this means is that you should never set tv_nsec past the value 1 billion—this would imply more than a one-second offset.)
Here are some examples:
it_value.tv_sec = 5;
it_value.tv_nsec = 500000000;
it_interval.tv_sec = 0;
it_interval.tv_nsec = 0;
This creates a one-shot timer that goes off in 5.5 seconds.
(We got the .5
because of the 500,000,000 nanoseconds
value.)
We're assuming that this is used as a relative timer, because if it weren't, then that time would have elapsed long ago (5.5 seconds past January 1, 1970, 00:00 GMT).
Here's another example:
it_value.tv_sec = 987654321;
it_value.tv_nsec = 0;
it_interval.tv_sec = 0;
it_interval.tv_nsec = 0;
This creates a one-shot timer that goes off Thursday, April 19, 2001 at
00:25:21 EDT.
(There are a bunch of functions that help you convert between the human-readable date and the number of
seconds since January 1, 1970, 00:00:00 GMT
representation. Take a look in the C library
at
time(),
asctime(),
ctime(),
mktime(),
strftime(),
etc.)
For this example, we're assuming that it's an absolute timer, because of the huge number of seconds that we'd be waiting if it were relative (987654321 seconds is about 31.3 years).
Note that in both examples, I've said, We're assuming
that…
There's nothing in the code for timer_settime() that checks
those assumptions and does the right
thing!
You have to specify whether the timer is absolute or relative yourself.
The kernel will happily schedule something 31.3 years into the future.
One last example:
it_value.tv_sec = 1;
it_value.tv_nsec = 0;
it_interval.tv_sec = 0;
it_interval.tv_nsec = 500000000;
Assuming it's relative, this timer will go off in one second, and then again every half second after that. There's absolutely no requirement that the reload values look anything like the one-shot values.
