【问题标题】:How to use timer in C?如何在 C 中使用计时器?
【发布时间】:2021-03-27 10:46:11
【问题描述】:

在 C 中使用计时器的方法是什么?我需要等到 500 毫秒才能找到工作。请提及完成这项工作的任何好方法。我使用了sleep(3); 但是这种方法在这段时间内没有做任何工作。我有一些东西会在那个时候尝试获得任何意见。

【问题讨论】:

  • 选择、投票、epoll……你想要什么?
  • @Eddy_Em 这些 select、poll、epoll 是什么?我想设置一个计时器,假设为 5 秒。如果用户在此时间内输入,则该输入将被视为有效。
  • 只需阅读man termios:您可以设置终端,使其等待 5 秒输入。如果没有任何输入 read 将返回 0,否则您可以从终端读取用户数据。
  • 你不能在纯标准 C 中使用计时器。你需要一些 operating system 支持。在 Linux 上,请仔细阅读 time(7)

标签: c timer countdowntimer


【解决方案1】:

这是我使用的一个解决方案(它需要#include <time.h>):

int msec = 0, trigger = 10; /* 10ms */
clock_t before = clock();

do {
  /*
   * Do something to busy the CPU just here while you drink a coffee
   * Be sure this code will not take more than `trigger` ms
   */

  clock_t difference = clock() - before;
  msec = difference * 1000 / CLOCKS_PER_SEC;
  iterations++;
} while ( msec < trigger );

printf("Time taken %d seconds %d milliseconds (%d iterations)\n",
  msec/1000, msec%1000, iterations);

【讨论】:

  • 什么是CLOCKS_PER_SEC
  • @mLstudent33 this macro is the number of clock ticks per second measured by the clock function source
  • 这是一个糟糕的解决方案,因为它会导致进程不必要地消耗处理器时间。
【解决方案2】:

您可以使用 time.h 中的 time_t 结构和 clock() 函数。

使用clock() 将开始时间存储在time_t 结构中,并通过比较存储时间与当前时间之间的差异来检查经过的时间。

【讨论】:

  • 应该在for循环内吗?
  • 这取决于你想做什么。如果你的程序基于一个大循环,你可以把它放在里面。否则,您必须创建一个专用线程来循环您的计时器。
  • 这是一个糟糕的解决方案,因为它会导致进程不必要地消耗处理器时间。
【解决方案3】:

是的,你需要一个循环。如果您已经有一个主循环(大多数 GUI 事件驱动的东西都有),您可能可以将您的计时器放入其中。使用:

#include <time.h> 
time_t my_t, fire_t;

然后(对于超过 1 秒的时间),通过读取当前时间来初始化您的计时器:

my_t = time(NULL);

添加您的计时器应等待的秒数并将其存储在 fire_t 中。 time_t 本质上是一个 uint32_t,您可能需要强制转换它。

在你的循环中做另一个

my_t = time(NULL);

if (my_t > fire_t) 然后考虑触发计时器并在那里做你想做的事情。这可能包括通过再次执行 fire_t = time(NULL) + seconds_to_wait 来重置它。

time_t 是一种有点过时的 unix 方法,将时间存储为自 1970 年 1 月 1 日午夜以来的秒数,但它有很多优点。对于小于 1 秒的时间,您需要使用 gettimeofday() (微秒)或 clock_gettime() (纳秒)并处理一个 struct timeval 或 struct timespec 这是一个 time_t 以及自 1 秒标记以来的微秒或纳秒。制作计时器的工作方式相同,除非当您添加等待时间时,如果生成的微秒或纳秒值超过 1 秒,您需要记住手动进行进位(进入 time_t)。是的,很乱。见 man 2 time,man gettimeofday,man clock_gettime。

sleep()、usleep()、nanosleep() 有一个隐藏的好处。你认为它暂停了你的程序,但他们真正做的是在这段时间内释放 CPU。通过读取时间并与完成时间进行比较来反复轮询(我们还在那里吗?)将消耗大量 CPU 周期,这可能会减慢在同一台机器上运行的其他程序的速度(并使用更多的电力/电池)。大部分时间最好是 sleep() 然后开始检查时间。

如果你想同时睡觉和工作,你需要线程。

【讨论】:

    【解决方案4】:

    这些例子可能对你有帮助

    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    
    /*
        Implementation simple timeout
    
        Input: count milliseconds as number
    
        Usage:
            setTimeout(1000) - timeout on 1 second
            setTimeout(10100) - timeout on 10 seconds and 100 milliseconds
     */
    void setTimeout(int milliseconds)
    {
        // If milliseconds is less or equal to 0
        // will be simple return from function without throw error
        if (milliseconds <= 0) {
            fprintf(stderr, "Count milliseconds for timeout is less or equal to 0\n");
            return;
        }
    
        // a current time of milliseconds
        int milliseconds_since = clock() * 1000 / CLOCKS_PER_SEC;
    
        // needed count milliseconds of return from this timeout
        int end = milliseconds_since + milliseconds;
    
        // wait while until needed time comes
        do {
            milliseconds_since = clock() * 1000 / CLOCKS_PER_SEC;
        } while (milliseconds_since <= end);
    }
    
    
    int main()
    {
    
        // input from user for time of delay in seconds
        int delay;
        printf("Enter delay: ");
        scanf("%d", &delay);
    
        // counter downtime for run a rocket while the delay with more 0
        do {
            // erase the previous line and display remain of the delay
            printf("\033[ATime left for run rocket: %d\n", delay);
    
            // a timeout for display
            setTimeout(1000);
    
            // decrease the delay to 1
            delay--;
    
        } while (delay >= 0);
    
        // a string for display rocket
        char rocket[3] = "-->";
    
        // a string for display all trace of the rocket and the rocket itself
        char *rocket_trace = (char *) malloc(100 * sizeof(char));
    
        // display trace of the rocket from a start to the end
        int i;
        char passed_way[100] = "";
        for (i = 0; i <= 50; i++) {
            setTimeout(25);
            sprintf(rocket_trace, "%s%s", passed_way, rocket);
            passed_way[i] = ' ';
            printf("\033[A");
            printf("| %s\n", rocket_trace);
        }
    
        // erase a line and write a new line
        printf("\033[A");
        printf("\033[2K");
        puts("Good luck!");
    
        return 0;
    }
    

    编译文件,运行后删除(我的偏好)

    $ gcc timeout.c -o timeout && ./timeout && rm timeout
    

    尝试自己运行看看结果。

    注意事项:

    测试环境

    $ uname -a
    Linux wlysenko-Aspire 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
    $ gcc --version
    gcc (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
    Copyright (C) 2015 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    

    【讨论】:

    • *** buffer overflow detected ***: /home/comp/Qt_project/timer_in_C/timer_in_C terminated 在 Ubuntu 中。我改变了for (i = 0; i &lt;= 40; i++) {,一切都很好:3
    • 这是一个糟糕的解决方案,因为它会导致进程不必要地消耗处理器时间。
    猜你喜欢
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 2019-07-28
    相关资源
    最近更新 更多