1

I have a requirement to set more than one interval-timers (alarms of same type : ITIMER_REAL) in the same process. so I used setitimer() system call to create 3 alarms with each timer having separate structures to hold time interval values. when any timer expires it will give a signal SIGALRM to the calling process, but i couldn't find which timer among three has given the signal and I don't even know whether all the timers are running or not. Is there any way to find which timer has given the signal... Thank you.

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>

void timer_handler (int signum)
{
 static int count = 0;
 printf ("timer1 expired %d times\n", ++count);
}


int main ()
{   
    int m = 0;
     struct sigaction sa;
     struct itimerval timer1, timer2, timer3;

     memset (&sa, 0, sizeof (sa));

     sa.sa_handler = &timer_handler;

     sigaction (SIGALRM/*SIGVTALRM*/, &sa, NULL);

     timer1.it_value.tv_sec = 1;
     timer1.it_value.tv_usec = 0;
     timer1.it_interval.tv_sec = 5;
     timer1.it_interval.tv_usec = 0;

     timer2.it_value.tv_sec = 2;
     timer2.it_value.tv_usec = 0/* 900000*/;
     timer2.it_interval.tv_sec = 5;
     timer2.it_interval.tv_usec = 0/*900000*/;

     timer3.it_value.tv_sec = 3;
     timer3.it_value.tv_usec = 0/* 900000*/;
     timer3.it_interval.tv_sec = 5;
     timer3.it_interval.tv_usec = 0/*900000*/;

     setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer1, NULL);
     setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer2, NULL);
     setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer3, NULL);

    while (1)
    {
        //printf("\nin main  %d",m++);
        //sleep(1);
    }
}
reddi hari
  • 173
  • 1
  • 12

2 Answers2

1

No, you only have one ITIMER_REAL timer per process. Using setitimer multiple times overwrites the previous value, see man setitimer

A process has only one of each of the three types of timers.

You can also see this, when you modify the intervals in your example code

timer1.it_interval.tv_sec = 1;
timer2.it_interval.tv_sec = 2;

and using nanosleep instead of sleep, because it might interfere with SIGALRM.

Now running the code, you will see only 5 second intervals.


You can also retrieve the previous set value by providing a second struct itimerval

struct itimerval old1, old2, old3;
setitimer(ITIMER_REAL, &timer1, &old1);
setitimer(ITIMER_REAL, &timer2, &old2);
setitimer(ITIMER_REAL, &timer3, &old3);

old1 will contain zero values, because it is the first time you use setitimer. old2 contains it_interval = 1 sec, and old3 contains it_interval = 2 sec. The it_values will be different, depending on how much time elapsed between the calls to setitimer.

So, if you need multiple timers, you need to do some bookkeeping. Each time a timer expires, you must calculate which timer is next and call setitimer accordingly.


As an alternative, you may look into POSIX timers. This allows to create multiple timers

A program may create multiple interval timers using timer_create().

and also pass some id to the handler via sigevent. Although the example at the end of the man page looks a bit more involved.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198
0

If I understand your question right you want to know the status of the different timers.

In the reference a getitimer function avalable:

The function getitimer() fills the structure pointed to by curr_value with the current setting for the timer specified by which (one of ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF). The element it_value is set to the amount of time remaining on the timer, or zero if the timer is disabled. Similarly, it_interval is set to the reset value.

You can find the full reference here Link

Hope that helps

  • Thanks for the answer, but my question is, can I create more than one alarm timer in the same process, and if I can then, since all timers give same kind of signal to the calling process when they expire (example: for all timers of type ITIMER_REAL the signal raised is SIGALRM), it has to execute the same signal handler function. So how can I get to know which timer has expired (or which timer has raised the signal), because depending the timer expired I would go to different state(FSM). – reddi hari Nov 27 '17 at 07:19
  • Hey, what I was thinking about is the getitimer() function. You can check all 3 of your timers and the one that changed its value is the one who recently expired. Example: SIGALARM -> getitimer() of all 3 -> 1, 3 are running and 2 is expired -> handle timer 2 timeout. – MartinLeitgeb Nov 28 '17 at 09:27