Вызов функции точно каждую секунду с использованием таймера? - PullRequest
0 голосов
/ 03 января 2012

Мне нужно вызывать функцию каждую секунду точно так же, как я хочу хранить данные, основанные на каждой секунде, чтобы я не мог пропустить секунду? Какой лучший метод в C?

Ниже приведен скелет метода timer_create, достаточно ли это надежно?

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

Ответы [ 5 ]

7 голосов
/ 03 января 2012

В Linux и других системах POSIX timer_create - это функция, которую вы ищете.Установите таймер для доставки через сигнал, и он будет очень надежным.Не используйте устаревшие ualarm или setitimer apis, которые устарели и имеют различные уродливые проблемы, с которыми вы, вероятно, не захотите сталкиваться, если вы уже не являетесь экспертом в Unix-средах реального времени ...

4 голосов
/ 03 января 2012

У вас есть два варианта вызова функции каждую вторую секунду:

  • Выполнение «ожидания ожидания»
  • Задержка вашего процесса / потока на некоторое время

Первый вариант, безусловно, более точный, но потребляет гораздо больше ресурсов процессора и менее отзывчив.Это можно просто сделать с помощью цикла while или for.

Вот небольшой пример того, как может выглядеть этот цикл busy-wait :

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

Второй вариант может быть менее точен (поскольку ваш процесс может ждать немного меньше или больше указанного времени), но это предпочтительный вариант с точки зрения многопроцессорности и планирования.Для этого вы можете использовать функцию sleep() / usleep() / Sleep() (зависит от вашей системы).В качестве альтернативы вы можете использовать сигналы.

3 голосов
/ 03 января 2012

ualarm(), вероятно, самый простой способ сделать это.Как уже упоминалось, идеальная точность не гарантируется, но разрешение, скорее всего, достаточно.

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

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

Я использовал signal для ясности, но sigaction / sigprocmask является более портативным и многофункциональным.

2 голосов
/ 03 января 2012

в Unix / Linux, вы можете использовать таймер, вот пример:

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

замените вашу собственную функцию на timeout_info

0 голосов
/ 03 января 2012

В Linux очень часто используется select() для синхронизации. Таким образом, вы также можете получать уведомления об активности файловых дескрипторов.

Вы должны иметь struct timeval для интервала и передать его в качестве последнего аргумента выбора.

...