7

是否有一个工作计时器的示例,它使用 C 每 x 秒执行一些功能。

我很感激一个示例工作代码。

4

4 回答 4

15

您可以生成一个新线程:

void *threadproc(void *arg)
{
    while(!done)
    {
        sleep(delay_in_seconds);
        call_function();
    }
    return 0;
}
...
pthread_t tid;
pthread_create(&tid, NULL, &threadproc, NULL);

alarm(2)或者,您可以使用or设置警报setitimer(2)

void on_alarm(int signum)
{
    call_function();
    if(!done)
        alarm(delay_in_seconds);  // Reschedule alarm
}
...
// Setup on_alarm as a signal handler for the SIGALRM signal
struct sigaction act;
act.sa_handler = &on_alarm;
act.sa_mask = 0;
act.sa_flags = SA_RESTART;  // Restart interrupted system calls
sigaction(SIGALRM, &act, NULL);

alarm(delay_in_seconds);  // Setup initial alarm

当然,这两种方法都有一个问题,即您定期调用的函数需要是线程安全的。

signal 方法特别危险,因为它还必须是异步安全的,这很难做到——即使是像printf不安全这样简单的事情,因为printf可能会分配内存,并且如果SIGALRM中断对 的调用malloc,你就会遇到麻烦,malloc因为不可重入。所以我不推荐使用信号方法,除非您所做的只是在信号处理程序中设置一个标志,该标志稍后会被其他一些函数检查,这会使您回到与线程版本相同的位置。

于 2012-12-17T23:50:55.173 回答
6

使用间隔计时器和信号有多种传统方法可以做到这一点,但我将介绍两种现代方法:

使用 POSIX 计时器

POSIXtimer_create函数创建一个计时器,该计时器可配置为在计时器到期时提供一次性或定期通知。创建计时器时,您可以通过信号或在新线程中请求传递。由于正确使用信号很复杂(对于信号处理程序可以做什么和不可以做什么有严格的规定,并且违反规则通常“似乎有效”,直到你不走运),我建议使用基于线程的交付。

用线程滚动你​​自己的计时器

这真的很简单。让一个新线程进入循环睡眠并在每次所需时间过去时做任何你需要做的事情。

于 2012-12-17T23:54:12.853 回答
1

如果我们不想要线程,我们可以使用sleep

int time = 10;
printf("time: %ds\n", time);
int i = 0;
while(i<time) {

        printf("doing stuff in duration %d\n", i);
        //stuff();
        sleep(1);
        i++;
}

东西每1s启动一次,所以我们希望能在这段时间内完成,否则它必须照顾资源。

于 2020-09-30T08:32:10.357 回答
0

IMO,在这种情况下,您可以利用gettimeofday()以下算法:使用while(1)计算当前时间和 last_execution_time 之间的时间差的算法,每次差值达到 1 秒,更新 last_execution_time 并调用应该每 1 秒运行的函数。

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

#DEFINE DESIRED_INTERVAL 1  //1 second
int get_tv_cur_minus_given(struct timeval *tv, struct timeval *tp_given, int *sign)
{
    struct timeval tp_cur;


    gettimeofday(&tp_cur,NULL);

    tv->tv_sec  = tp_cur.tv_sec - tp_given->tv_sec;
    tv->tv_usec = tp_cur.tv_usec - tp_given->tv_usec;

    if(tv->tv_sec > 0) {
        *sign = 1;
        if(tv->tv_usec < 0) {
            tv->tv_sec--;
            tv->tv_usec = 1000000 + tv->tv_usec;
        }
    }else
    if(tv->tv_sec == 0) {
        if(tv->tv_usec == 0)
            *sign = 0;
        else
        if(tv->tv_usec < 0) {
            *sign = -1;
            tv->tv_usec *= -1;
        }else
            *sign = 1;
    }else {
        *sign = -1;
        if(tv->tv_usec > 0) {
            tv->tv_sec++;
            tv->tv_usec = 1000000 - tv->tv_usec;
        }else
        if(tv->tv_usec < 0)
            tv->tv_usec *= -1;
    return 0;
        }
}

int main()
{
    struct timeval      tv_last_run;
    struct timeval  tv_diff;
    int sign;


    while(true)
    {

     get_tv_cur_minus_given(&tv_diff, &tv_last_run, &sign);

        if(tv_diff.tv_sec > DESIRED_INTERVAL)
        {
            gettimeofday(&tv_last_run,NULL);
            printf("\ncall the func here");
        }
    }

    return 0;
}

如果您需要主线程之外的不同线程,请将 main() 中的行移动到函数指针中并通过 pthread_create 函数传递它,例如:

void *threadproc(void *arg)
{
   while(1)
   {
       //put the same lines as inside main() function in above code snippet. .
   }
}
pthread_create(&tid, NULL, &threadproc, NULL);
于 2018-09-01T18:29:35.010 回答