Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用计时器精确地每秒调用一个函数?_C_Timer_Signals - Fatal编程技术网

C 使用计时器精确地每秒调用一个函数?

C 使用计时器精确地每秒调用一个函数?,c,timer,signals,C,Timer,Signals,我需要每秒调用一个函数,就像我希望基于每秒调用的函数来存储数据一样,这样我就不会错过第二个了?C语言中最好的方法是什么 下面是计时器创建方法的框架,这足够可靠吗 #include <stdio.h> #include <time.h> #include <signal.h> timer_t gTimerid; void start_timer(void) { struct itimerspec value; value.it_va

我需要每秒调用一个函数,就像我希望基于每秒调用的函数来存储数据一样,这样我就不会错过第二个了?C语言中最好的方法是什么

下面是计时器创建方法的框架,这足够可靠吗

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

有两种方法可以每隔一秒钟调用一个函数:

忙着等待 使进程/线程睡眠一段时间 第一个选项肯定更精确,但CPU消耗更大,响应速度更低。它可以简单地用一段时间或循环完成

下面是一个繁忙等待循环的小示例:

#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,具体取决于您的系统功能。或者,您可以使用信号。

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

在Linux上,用自己的函数代替timeout\u info在计时时使用select是非常常见的。通过这种方式,还可以通知您有关文件描述符活动的信息

您需要为interval设置一个struct timeval,并将其作为select的最后一个参数传递。

ualarm可能是最简单的方法。正如其他人提到的,不能保证完美的准确性,但分辨率可能足够了

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

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


为了清晰起见,我使用了signal,但sigaction/sigprocmask更具便携性和功能。

在Linux和其他POSIX系统上,您需要的功能是创建计时器。将计时器设置为通过信号发送,它将非常可靠。不要使用过时的ualarm或setitimer API,因为这些API已被弃用,并且存在各种各样的丑陋问题,除非您已经是实时unix方面的专家……

fork标记的链接是什么?不可能精确地每1秒调用一个函数。即使您的CPU时钟从铯原子钟获得脉冲,即使原子钟有公差(尽管公差很小),也没有任何东西可以阻止大型操作系统(如Linux、Windows、Mac)抢占您的程序线程。你愿意容忍多少?或者您是否考虑过一种不依赖于这种严格公差的策略?您需要一个计时器,它将是特定于平台的。那么,您需要哪些平台?可能的重复:将您以前的一些问题标记为已回答。从:计时器将不会在请求的时间之前过期,但可能会在之后的短时间内过期,这取决于系统计时器分辨率和系统负载。不过,这可能已经足够好了。@manuzhang将在每秒钟发射一次,并每隔一秒钟继续发射一次,而不必担心之前有人打过电话。@user837306在这种情况下,您可以使用setitimerITIMER\u REAL、&val、NULL和sigactionSIGALRM、&act、NULL;如果您使用的是Linux,请尝试man setitimer,并且已满illustration@manuzhangtimer_create是一个更好的选项吗?你能检查一下我用一些示例代码编辑了我的第一篇文章吗?你的建议是在一定时间后睡觉,是吗?据我所知,忙碌等待是一种非常糟糕的做法,不是吗?@Milo:这取决于用例。例如,在游戏中,它很常用,因为您希望分配尽可能多的CPU时间,以避免由于调度程序而导致的微滞后。@user837306:是的,完全正确。睡眠功能或其派生功能将在给定的时间内暂停您的过程。在while循环中,通过定期检查时间,也可以实现同样的效果。@constantinius问题是,就在这一秒,我想启动它并进行处理。接下来的第二秒,我也要启动它来处理,等等,这个方法会工作吗?所以在这种情况下,尽管函数的前一次调用正在执行某些函数,但每秒都会调用下一个函数,对吗。但是,当每秒钟的执行时间都超过一秒时,您会遇到奇怪的行为。Dave,那么在这种情况下,您建议的最佳解决方案是什么以避免出现奇怪的行为。@user837306请确保每秒钟运行一次。否则,您需要采取许多与编写线程程序相同的预防措施。您还需要使用sigprocmask和sigaction来确保您可以在SIGALRM处理程序中接收SIGALRM。如果它正在运行,下一秒需要调用它,会不会出现问题?亲爱的R。。因此,timer_create是time.h库的一部分。那么它会在一秒钟内调用函数吗?我发现这个链接就是你的意思吗?@R我在网上发现了一些代码,可以用作我的骨架吗?我不知道如何在回调函数中打印时间?我把代码放进去,它总是不见了,为什么?我还能把代码放在哪里?@R我现在已经用代码更新了我的第一篇帖子,如果需要的话,需要你的评论 可以?