Toga
Toga

Reputation: 19

How to get every integer second in a c program

I am wondering if there is a way to get every integer second in a c program. I tried to use 'gettimeofday' function to get the current time and then if the current fractional part of second falls into a region (say larger than 0.9 and smaller than 0.1), I rounded the current time into an integer. However, when I run the program, occasionally, there were a few seconds missed. Does anyone have a better solution?

Thanks

Upvotes: 0

Views: 186

Answers (1)

Matthias
Matthias

Reputation: 8180

I would suggest to use the alarm signal:

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

void timer_handler (int signum)
{
  struct timeval tval;
  gettimeofday(&tval, NULL);
  printf("Seconds: %ld\n",tval.tv_sec);
}

int main ()
{
  struct sigaction sa;
  struct itimerval timer;

  memset (&sa, 0, sizeof (sa));
  sa.sa_handler = &timer_handler;
  sigaction (SIGVTALRM, &sa, NULL);

  timer.it_value.tv_sec = 1;
  timer.it_value.tv_usec = 0;
  timer.it_interval.tv_sec = 1;
  timer.it_interval.tv_usec = 0;
  setitimer (ITIMER_VIRTUAL, &timer, NULL);

  while (1);
}

At my Mac (OS X 10.11.5) I get:

./alarm
Seconds: 1468937712
Seconds: 1468937713
Seconds: 1468937714
Seconds: 1468937715
Seconds: 1468937716
Seconds: 1468937717
Seconds: 1468937718
Seconds: 1468937719
Seconds: 1468937720

EDIT

The code above uses the virtual timer, that only ticks als long the thread is running (and thus relies on the busy loop the introduce the high load). Using the real timer allows for reduction of the load:

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

void timer_handler (int signum)
{
  struct timeval tval;
  printf("Foo");
  gettimeofday(&tval, NULL);
  printf("Seconds: %ld\n",tval.tv_sec);
}

int main ()
{
  struct sigaction sa;
  struct itimerval timer;
  sa.sa_mask=0;
  sa.sa_flags=0;


  memset (&sa, 0, sizeof (sa));
  sa.sa_handler = &timer_handler;
  sigaction (SIGALRM, &sa, NULL);

  timer.it_value.tv_sec = 1;
  timer.it_value.tv_usec = 0;
  timer.it_interval.tv_sec = 1;
  timer.it_interval.tv_usec = 0;
  setitimer (ITIMER_REAL, &timer, NULL);

  while (1){
    pthread_yield_np();
  }
}

This approach runs basically the timer handler only. Thus the OS shouldn't care to much about load. However, be aware that hard real-time guarantees one get by OS's real-time features only (if there are any).

Upvotes: 0

Related Questions