Как получить каждую целую секунду в программе переменного тока

Мне интересно, есть ли способ получить каждую целую секунду в программе переменного тока. Я попытался использовать функцию "gettimeofday", чтобы получить текущее время, а затем, если текущая дробная часть секунды попадает в область (скажем, больше 0,9 и меньше 0,1), я округлил текущее время в целое число. Однако, когда я запускаю программу, иногда пропускаются несколько секунд. У кого-нибудь есть лучшее решение?

Спасибо

1 ответ

Я бы предложил использовать сигнал тревоги:

#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);
}

На моем Mac (OS X 10.11.5) я получаю:

./тревога
Секунды: 1468937712
Секунды: 1468937713
Секунды: 1468937714
Секунды: 1468937715
Секунды: 1468937716
Секунды: 1468937717
Секунды: 1468937718
Секунды: 1468937719
Секунды: 1468937720

РЕДАКТИРОВАТЬ

Приведенный выше код использует виртуальный таймер, который тикает только в течение всего времени работы потока (и, таким образом, полагается на занятый цикл при высокой нагрузке). Использование реального таймера позволяет снизить нагрузку:

#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();
  }
}

Этот подход работает в основном только с обработчиком таймера. Таким образом, ОС не должна заботиться о нагрузке. Однако следует помнить, что жесткие гарантии реального времени позволяют получить только функции ОС в реальном времени (если они есть).

Другие вопросы по тегам