0

I need to call a function every second exactly as I want to store the data based on the every second so I cannot miss the second? What is best method in C?

Below is a skeleton of the timer_create method is this reliable enough?

#include <stdio.h>
#include <time.h>
#include <signal.h>

timer_t gTimerid;

void start_timer(void)
{        
  struct itimerspec value;

  value.it_value.tv_sec = 1;
  value.it_value.tv_nsec = 0;  
  value.it_interval.tv_sec = 1;
  value.it_interval.tv_nsec = 0;

  timer_create (CLOCK_REALTIME, NULL, &gTimerid);    
  timer_settime (gTimerid, 0, &value, NULL);
}

void stop_timer(void)
{        
  struct itimerspec value;

  value.it_value.tv_sec = 0;
  value.it_value.tv_nsec = 0;    
  value.it_interval.tv_sec = 0;
  value.it_interval.tv_nsec = 0;

  timer_settime (gTimerid, 0, &value, NULL);        
}

void timer_callback(int sig)
{    
  printf(" Catched timer signal: %d ... !!\n", sig);     
}

int main(int ac, char **av)
{
    (void) signal(SIGALRM, timer_callback);
    start_timer();
    while(1);
}
jww
  • 97,681
  • 90
  • 411
  • 885
user837306
  • 857
  • 3
  • 18
  • 32
  • 2
    what is the link with the fork tag ? – Cédric Julien Jan 03 '12 at 14:49
  • 7
    It's impossible to call a function every 1 second *exactly*. Even if your CPU clock is getting pulses from a cesium atomic clock (even atomic clocks have tolerances, albeit very small ones), there's nothing preventing a large operating system (e.g. Linux, Windows, Macs) from preempting your program's threads. How much tolerance are you willing to allow? Or have you considered a strategy that doesn't depend on such tight tolerances? – In silico Jan 03 '12 at 14:49
  • 1
    You want a timer, which will be platform-specific. So, which platform(s) do you need? – Useless Jan 03 '12 at 14:50
  • Possible duplicate of: http://stackoverflow.com/questions/5209408/sleeping-for-an-exact-duration – Dan Fego Jan 03 '12 at 14:50
  • 3
    mark some of your previous questions as answered. – nothrow Jan 03 '12 at 14:50
  • This depends on the platform your program runs on. – C-F Jan 03 '12 at 14:51
  • Regarding tolerance: from *"... every second ..."* I'd conclude the maximum tolerance is half a second. – alk Jan 03 '12 at 15:24
  • I will be running centos. So what best strategy you guys suggestion based on previous experiences? – user837306 Jan 03 '12 at 15:55
  • Possible duplicate of [Execute a method every x seconds in C](https://stackoverflow.com/q/13923885/608639) – jww Sep 01 '18 at 16:37

5 Answers5

7

On Linux and other POSIX systems, timer_create is the function you're looking for. Set the timer to be delivered via a signal and it will be very reliable. Don't use the older ualarm or setitimer apis which are deprecated and have various ugly issues that you probably don't want to get into unless you're already an expert on realtime unix stuff...

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Dear R.. so timer_create is part of time.h library. So will it call the function exactly at the very one second is it. – user837306 Jan 04 '12 at 02:56
  • I found this link http://www.qnx.com/developers/docs/6.3.2/neutrino/lib_ref/t/timer_create.html is that what you meant? – user837306 Jan 04 '12 at 03:06
  • @R I have added some codes which I found on the net is this ok to be used as my skeleton I do not know how to print the time in the callback function? – user837306 Jan 06 '12 at 05:55
  • I put the codes and it goes missing always why ya? where else can I put the codes? – user837306 Jan 07 '12 at 14:44
  • @R I have updated now my first post with the codes need your comments on it if that is ok? – user837306 Jan 07 '12 at 17:50
4

You have two options to call a function every other second:

  • Do a "busy wait"
  • Make your process/thread sleep for an amount of time

The first option is definitely more accurate but a lot more CPU consumptive and less responsive. It can simply be done with a while or for loop.

Here a small example of how this busy-wait loop might look like:

#include <time.h>

#define TIME_TO_WAIT 1 /* wait for one second */
...
clock_t last = clock();
while(1) {
    clock_t current = clock();
    if (current >= (last + TIME_TO_WAIT * CLOCKS_PER_SEC)) {
        yourSpecialFunction(); /* insert your function here */
        last = current;
    }
}

The second option is maybe less accurate (since your process may wait a little less or more than the specified time) but it is the preferred option in terms of multiprocessing and scheduling. You can use your systems sleep()/usleep()/Sleep() (depends on your system) function for it. Alternatively you can use signals.

Constantinius
  • 34,183
  • 8
  • 77
  • 85
  • So your suggestion is go to sleep then after certain time wake is it? – user837306 Jan 03 '12 at 15:56
  • As far as I know "busy wait" is a very bad practice, isn't it? – Bakudan Jan 03 '12 at 15:59
  • @Milo: That depends on the usecase. In games, for example, it is commonly used, since you want to allocate as much CPU time as possible, to avoid micro lags due to the scheduler. – Constantinius Jan 04 '12 at 09:56
  • @user837306: yes, exactly. The `sleep` function (or derivates of it) will pause your process for a given amount of time. The same can be achieved in the `while`-loop with a periodical checking of the time. – Constantinius Jan 04 '12 at 09:59
  • @constantinius the problem is that at the very second I want to fire it and do the processing. following that the next very second also I want to fire it to do processing and so on will this method work? – user837306 Jan 05 '12 at 00:45
  • @user837306: Yes it will work. I'll update my answer for a example of that loop. – Constantinius Jan 05 '12 at 10:24
  • `clockt_t` should be `clock_t` in line 5. – utarid Nov 26 '14 at 08:06
3

ualarm() is probably the simplest way of doing this. As others have mentioned, perfect accuracy isn't guaranteed, but the resolution is likely sufficient.

void each_sec(int x)
{
     printf("%d", (int)time(NULL));
}

int main()
{
    signal(SIGALRM, each_sec);
    ualarm(1000000, 1000000);
}

I used signal for clarity, but sigaction/sigprocmask is more portable and featureful.

Dave
  • 10,964
  • 3
  • 32
  • 54
  • So in this case every second despite the earlier call of the function is doing some function it will call the next right? – user837306 Jan 03 '12 at 15:57
  • Right. You run into weird behavior when each_sec takes longer than a second to execute, though. – Dave Jan 03 '12 at 16:02
  • Dave,then what best solution you suggest in that case to avoid weird behavior. – user837306 Jan 04 '12 at 02:57
  • @user837306 Make sure `each_sec` runs in a second. Otherwise you'd need to take many of the same precautions as you would if writing a threaded program. You'd also need to use `sigprocmask` and `sigaction` to make sure that you can receive `SIGALRM` within a `SIGALRM` handler. – Dave Jan 04 '12 at 12:57
  • how about if it is running and the next second needs to call it will there be a problem here? – user837306 Jan 05 '12 at 00:47
2

on Unix/Linux, you can use a timer, here's an example:

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



int limit = 10;
/* signal process */
void timeout_info(int signo)
{
   if(limit == 0)
   {
       printf("Sorry, time limit reached.\n");
       exit(0);
   }
   printf("only %d senconds left.\n", limit--);
}

/* init sigaction */
void init_sigaction(void)
{
    struct sigaction act;

    act.sa_handler = timeout_info;
    act.sa_flags   = 0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGPROF, &act, NULL);
} 

/* init */
void init_time(void)
{
    struct itimerval val;

    val.it_value.tv_sec = 1;
    val.it_value.tv_usec = 0;
    val.it_interval = val.it_value;
    setitimer(ITIMER_PROF, &val, NULL);
}


int main(void)
{
    char *str;
    char c;

    init_sigaction();
    init_time();
    printf("You have only 10 seconds for thinking.\n");

    while(1);
    exit(0);
}

substitute your own function for timeout_info

Dave
  • 10,964
  • 3
  • 32
  • 54
manuzhang
  • 2,995
  • 4
  • 36
  • 67
  • From the [man page](http://linux.die.net/man/2/setitimer): "Timers will never expire before the requested time, but **may expire some (short) time afterward**, which depends on the system timer resolution and on the system load". This might be good enough, though. – Fred Larson Jan 03 '12 at 15:10
  • @manuzhang will it fire exactly at the very second and keep doing that every other second with out bothering there is a previous call made. – user837306 Jan 05 '12 at 00:46
  • @user837306 in that case you may use `setitimer(ITIMER_REAL,&val,NULL)` and `sigaction(SIGALRM,&act,NULL)`;if you are on Linux try `man setitimer` and there is full illustration – manuzhang Jan 05 '12 at 01:24
  • @manuzhang is timer_create a better option can you check I have edited my first post with some sample codes – user837306 Jan 08 '12 at 16:50
0

On Linux it is very common to use select() for timing. This way you can also be notified about file descriptors activity.

You need to have a struct timeval for interval and pass it as the last argument of select.

eyalm
  • 3,366
  • 19
  • 21