是否有一个工作计时器的例子,它使用C来每x秒执行一些函数。
我很欣赏一个工作代码示例。
答案 0 :(得分:14)
你可以产生一个新线程:
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)
或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
当然,这两种方法都存在这样的问题,即您定期调用的函数需要是线程安全的。
信号方法特别危险,因为它也必须是异步安全的,这很难做到 - 即使像printf
这样简单的事情也是不安全的,因为printf
可能会分配内存,如果SIGALRM
中断了对malloc
的调用,您遇到了麻烦,因为malloc
不可重入。所以我不建议使用signal方法,除非你所做的只是在信号处理程序中设置一个标志,后来由其他一些函数检查,这会让你回到与线程版本相同的位置。
答案 1 :(得分:6)
使用间隔定时器和信号有各种传统方法可以做到这一点,但我将介绍两种现代方法:
POSIX timer_create
功能创建一个计时器,可配置为在计时器到期时提供一次性或定期通知。创建计时器时,您可以通过信号或新线程请求传递。由于正确使用信号很复杂(对信号处理程序可以做什么和不能做什么都有严格的规定,而且经常打破规则"似乎工作"直到你不幸),我建议使用线程 - 基于交付。
这听起来真的很简单。创建一个进入循环休眠状态的新线程,并在每次所需时间结束时执行所需操作。
答案 2 :(得分: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++;
}
这些东西每1秒钟启动一次,因此我们希望可以在这段时间内完成,否则必须占用资源。
答案 3 :(得分: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);