Traditional Approach to Timers
Timer mechanisms in Linux and Unix-based systems have evolved to serve various needs. Different approaches can help you solve different types of problem. However, you’ll often see the first version of the alarm() mechanism still in use.
The alarm function is the simplest way to use a timer; here’s its prototype:
Using this method, you can only specify the time in whole seconds. When the time is up, the operating system sends the SIGALRM signal to your application. To process the timer’s expiry in your application, you should also define a callback function.
Here is an example of a signal handler function:
This code raises a SIGALRM signal after 1 second. If you want to increase the timer delay to five seconds, just call alarm(5) instead. To stop the timer, pass a value of 0: alarm(0).
When the time is up, the timer you use will not restart periodically. For example, if you want to delay for another second, you should restart the mechanism with another call to alarm().
Despite its ease of use, this method has some disadvantages:
Only one timer at a time. No periodic timer support. You can only give the time period in multiples of whole seconds. No way to know how much time remains on a timer.
Save the sample code given above as alarm.c. When you compile and run it, the program will call the timer_callback function after one second. It will then wait for the remaining two seconds due to the sleep(3) line, then terminate.
The reason for using the time command is to be able to see the times. But if you look at the result, the total running time is not three seconds. This is due to the SIGALRM signal from alarm(1) when the first second is up, while the syscall caused by the sleep(3) function is running. When this signal arrives, it interrupts the syscall initiated for sleep(3).
Using an Interval Timer
The interval timer mechanism was first available in version 4.2 BSD. It was later standardized by POSIX. Its main advantages over the traditional alarm() based timer method are:
Provides microsecond resolution. It allows controlling the time measurement in more detail over three different modes. It is possible to set it once and make it work periodically. It is possible to find out how long it is present at any given moment.
Function prototypes used for interval timer operations are as follows:
If you want to set up an interval timer, you’ll need to use the itimerval struct. You’ll need to pass a value using this struct as the second argument to the settimer function.
For example, an interval timer that will notify your application for 1 second and then every 300 milliseconds can be set up as follows:
If there is an interval timer active before the new values are set, its values are transferred to the variable address of the itimerval type given to the third parameter of the function.
You can set up three different types of timers with the interval timer mechanism. Specify the timer type in the first parameter of setitimer():
You can see from this table that the ITIMER_REAL type sends a SIGALRM signal, just like the alarm() function.
Using an interval timer and alarm() in the same application will be confusing. Although you can make a second check on the remaining time with gettimer(), it does not make sense to use them simultaneously.
Here is an example of defining the signal handler function with the debug header:
The above code uses the sleep() function to wait for three seconds. During this time, an interval timer runs, first for one second, then on an interval of 300 milliseconds.
For better understanding, save and compile the sample code with the name interval.c:
As you can see from the output after the timer runs, it calls the callback function every 300 milliseconds.
However, after waiting a little longer, you’ll notice that the application does not terminate. It continues to run the callback function every 300 milliseconds. If you increase the interval value in milliseconds, you will see that the application terminates. This is because of the usage area of the sleep() function.
Importance of Using Timers in Linux
Especially for real-time applications, the timer mechanism is of great importance. This is also a solution used for performance optimizations. You can even use it to measure uptime or latency in your application. It is important to use timer mechanisms to keep track of elapsed time and time transition events.