Как получить каждую целую секунду в программе переменного тока
Мне интересно, есть ли способ получить каждую целую секунду в программе переменного тока. Я попытался использовать функцию "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();
}
}
Этот подход работает в основном только с обработчиком таймера. Таким образом, ОС не должна заботиться о нагрузке. Однако следует помнить, что жесткие гарантии реального времени позволяют получить только функции ОС в реальном времени (если они есть).