signal handling question

  • fox_hound_33
  • Newbie
  • Newbie
  • fox_hound_33
  • Posts: 5

Post 3+ Months Ago

Hello all,

I am starting to learn signal handling in Linux and have been trying out some simple codes to deal with SIGALRM. The code shown below sets a timer to count down. When the timer is finished a SIGALRM is produced. The handler for the signal just increments a variable called count. This is repeated until the user hits ‘q’ in the keyboard. The code is shown below:

------------------------------------------------------------
Code: [ Select ]
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <stdlib.h>

void my_action(int);

int count = 0;

int main(int argc, char** argv)
{
    struct sigaction sigalrm_action;
    struct itimerval timer;
    
    timer.it_interval.tv_sec = 0; //Deal only in usec
    timer.it_interval.tv_usec = 1000;
    timer.it_value.tv_sec = 0; //Deal only in usec
    timer.it_value.tv_usec = 1000;

    sigalrm_action.sa_handler = my_action;
    sigemptyset(&sigalrm_action.sa_mask);
    sigalrm_action.sa_flags = 0;
    
    sigaction(SIGALRM, &sigalrm_action, 0);            

    printf("Hit any key to start, q to exit\n");    
    getchar();
        
    if(setitimer(ITIMER_REAL, &timer,NULL) != 0){
        perror("Error starting timer");
        exit(1);
    } 
    while(getchar()!= 'q');
    printf("Bye bye\n");
    return 0;
}

void my_action(int signum)
{
    count++;
    printf("Count is %d\n", count);
}
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <signal.h>
  4. #include <sys/time.h>
  5. #include <stdlib.h>
  6. void my_action(int);
  7. int count = 0;
  8. int main(int argc, char** argv)
  9. {
  10.     struct sigaction sigalrm_action;
  11.     struct itimerval timer;
  12.     
  13.     timer.it_interval.tv_sec = 0; //Deal only in usec
  14.     timer.it_interval.tv_usec = 1000;
  15.     timer.it_value.tv_sec = 0; //Deal only in usec
  16.     timer.it_value.tv_usec = 1000;
  17.     sigalrm_action.sa_handler = my_action;
  18.     sigemptyset(&sigalrm_action.sa_mask);
  19.     sigalrm_action.sa_flags = 0;
  20.     
  21.     sigaction(SIGALRM, &sigalrm_action, 0);            
  22.     printf("Hit any key to start, q to exit\n");    
  23.     getchar();
  24.         
  25.     if(setitimer(ITIMER_REAL, &timer,NULL) != 0){
  26.         perror("Error starting timer");
  27.         exit(1);
  28.     } 
  29.     while(getchar()!= 'q');
  30.     printf("Bye bye\n");
  31.     return 0;
  32. }
  33. void my_action(int signum)
  34. {
  35.     count++;
  36.     printf("Count is %d\n", count);
  37. }

----------------------------------------------------------

The problem I am facing is this, when I set the timer for 1000000usec it works fine (i.e 1sec). However if I keep reducing the usec time to 100000, 10000, 1000 etc the timing seems to be too slow. The count variable is not being incremented as fast as it should be. Why is this? I have a hunch I am doing some silly mistake here but I am not sure what it is.

Any help would be greatly appreciated.
  • Anonymous
  • Bot
  • No Avatar
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post 3+ Months Ago

  • casablanca
  • Proficient
  • Proficient
  • User avatar
  • Posts: 481

Post 3+ Months Ago

I can only think of two possible reasons for your problem:

1. Maybe the method by which you measure the time interval is bad. I/O functions such as printf usually take pretty long to execute, so at lower timer intervals, your timer would fire faster than it would take a printf to complete.

2. I'm not sure how setitimer is implemented, but usually, the OS handles timers using interrupts. The timer interrupt usually fires every few milliseconds, so that's possibly the smallest interval any application timer can count.
  • fox_hound_33
  • Newbie
  • Newbie
  • fox_hound_33
  • Posts: 5

Post 3+ Months Ago

casablanca wrote:
I can only think of two possible reasons for your problem:

1. Maybe the method by which you measure the time interval is bad. I/O functions such as printf usually take pretty long to execute, so at lower timer intervals, your timer would fire faster than it would take a printf to complete.

---> It could be that printf is taking too long as you said but i cant imagine printf taking more than 10ms (the problem starts when i set the timer to 10ms or lower). Any idea how much time printf takes?


2. I'm not sure how setitimer is implemented, but usually, the OS handles timers using interrupts. The timer interrupt usually fires every few milliseconds, so that's possibly the smallest interval any application timer can count.

---> I thought of this too. Is there any means to find out what is the smallest resolution timer available to the OS?

  • casablanca
  • Proficient
  • Proficient
  • User avatar
  • Posts: 481

Post 3+ Months Ago

fox_hound_33 wrote:
Any idea how much time printf takes?

You can get an estimate by using the times function before and after your printf call.

fox_hound_33 wrote:
Is there any means to find out what is the smallest resolution timer available to the OS?

I'm not too sure. Since there are functions like usleep which sleep take an argument in microseconds, there must be some other way by which the OS calculates times.
  • fox_hound_33
  • Newbie
  • Newbie
  • fox_hound_33
  • Posts: 5

Post 3+ Months Ago

What i gather from the man pages is that any time function (sleep(), usleep(), settimer etc) will never expire precisely at the specified point, it will expire slightly afterwards.

I ran some test code using usleep and found some interesting results.
When i put usleep to 0.1secs, the actual sleeping time varies from the set point (0.1secs) with an error of about +5%. The same error percentage jumps to about +40% when i put usleep to 0.01sec and the same error jumps to about +300%(!!!!) when i put usleep to 0.001sec.

Looks like as the timer resolution is brought down the error keeps increasing. Could be due to system timer resolution as mentioned. This could explain why settimer was behaving strangely for low values of time.

or perhaps there is some other reason??????????
  • casablanca
  • Proficient
  • Proficient
  • User avatar
  • Posts: 481

Post 3+ Months Ago

fox_hound_33 wrote:
any time function (sleep(), usleep(), settimer etc) will never expire precisely at the specified point, it will expire slightly afterwards.

Yes, that's because the calling thread will be put to sleep and it will be woken up only during the next context switch after the time period expires. So as your timer interval nears the context switch interval, the error will increase. And context switching is itself usually dependent on the timer interrupt, so there you go. :)

Apart from the timer, the signaling mechanism could be another potential bottleneck, i.e. how quickly the signal handler is called after a signal is raised.
  • Daemonguy
  • Moderator
  • Web Master
  • User avatar
  • Posts: 2700
  • Loc: Somewhere outside the box in Sarasota, FL.

Post 3+ Months Ago

I would be inclined to concur with the aforementioned assessment; the operation is taking longer than the timeout thus causing it to delay the output.
  • Mc_Gregor
  • Born
  • Born
  • Mc_Gregor
  • Posts: 1

Post 3+ Months Ago

Hi everyone ..
I am wanting to use the setitimer to run a timer in a cycle to run for some lines and I am more than bundled with it .. someone could give me a hand? ..

Code: [ Select ]
struct itimerval val;

val.it_interval.tv_sec = 0;
val.it_interval.tv_usec = interv;

val.it_value.tv_sec = 0;
val.it_value. tv_usec = interv;
setitimer (ITIMER_VIRTUAL, & val, NULL);

for (i = 0; i <can not; i + +)

(
sentences to run ..
)
  1. struct itimerval val;
  2. val.it_interval.tv_sec = 0;
  3. val.it_interval.tv_usec = interv;
  4. val.it_value.tv_sec = 0;
  5. val.it_value. tv_usec = interv;
  6. setitimer (ITIMER_VIRTUAL, & val, NULL);
  7. for (i = 0; i <can not; i + +)
  8. (
  9. sentences to run ..
  10. )


The idea is that the sentences run a while and start again after you finish your stopwatch, until the cycle ..
I appreciate the help ..

Post Information

  • Total Posts in this topic: 8 posts
  • Users browsing this forum: No registered users and 44 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.