timer_start() 睡眠后的 C 不起作用

Posted

技术标签:

【中文标题】timer_start() 睡眠后的 C 不起作用【英文标题】:C after timer_start() sleep is not working 【发布时间】:2019-01-21 07:24:01 【问题描述】:

我在 ubuntu 上使用 eclipse IDE 来编译我的 c 项目。我有一个计时器。启动定时器后,睡眠或睡眠功能不工作。 这是代码;

编辑

/*
 ============================================================================
 Name        : TimerTest.c
 Author      : FK
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>         /* , getenv() */
#include <getopt.h>
#include <unistd.h>         /* exec(), daemon() */
#include <stdint.h>
#include <string.h>         /* memset(), strerror() */
#include <errno.h>          /* errno */
#include <libgen.h>         /* basename() */
#include <signal.h>
#include <sys/timex.h>      /* ntp_gettime() */
#include <time.h>

#include "timer/timer.h"

#define CONFIG_TIMER_INTERVAL   100 /* in ms */
/* global vars decalarations */

static uint8_t _terminate = 0;
static int _signo = 0;

static int init_prg(int argc, char *argv[]);
static void timer_callback(void);

/* function implementations */
static void sig_handler(int signo)

    /* http://www.yolinux.com/TUTORIALS/C++Signals.html */
    _signo = signo;
    switch (signo)
    
        case SIGINT: /* Program interrupt. (ctrl-c) */

            _terminate = 1;
            break;
        case SIGTERM:

            _terminate = 1;
            break;
            /* SIGKILL, SIGSTOP yakalanımıyor! */
        default:

            break;
    



int main(int argc, char *argv[])

    init_prg(argc, argv);
    /* start super loop */
    while (1)
    
        printf("test!\n");
        //usleep(1000000);
        sleep(1);

    


static int init_prg(int argc, char *argv[])

    int res = -1;

    if (signal(SIGINT, sig_handler) == SIG_ERR)
    
        //exit(EXIT_FAILURE);
    

    /* Termination, Generated by "kill" command. */
    if (signal(SIGTERM, sig_handler) == SIG_ERR)
    
        //exit(EXIT_FAILURE);
    



    start_timer(2000, &timer_callback);

    if (res != 0)
    
        //exit(EXIT_FAILURE);
    

    return res;


static void timer_callback(void)

    printf("timer works!\n");

执行程序后,它会回显“测试!”迅速。忽略 sleep 或 usleep 命令。如果我注释掉 start_timer 行,它会休眠,在定时器之后它不是。有什么想法吗?

【问题讨论】:

请发布完整的代码示例。现在还不清楚这段代码应该如何表现。 除非我们看到start_timer() 在做什么,否则很难诊断。我怀疑您正在触发SIGALRM 信号。使用setitimer(ITIMER_REAL, ...) 创建的计时器将在到期时生成这样的信号。这足以从sleep()ing 唤醒线程/程序。 【参考方案1】:

您没有显示用于启动计时器的标准化接口。

不管POSIX specifies,usleep

的交互
nanosleep()
setitimer()
timer_create()
timer_delete()
timer_getoverrun()
timer_gettime()
timer_settime()
ualarm()
sleep()

未指定。

nanosleep 应该没有这个问题。

来自nanosleep's manpage:

与 sleep(3) 和 usleep(3) 相比,nanosleep() 有以下几点 优点:它为指定睡眠提供了更高的分辨率 间隔; POSIX.1 明确指定它不与 信号;它使恢复睡眠的任务 更容易被信号处理程序中断。

以上建议将您的usleep 替换为:

#include <unistd.h>
int my_usleep(useconds_t Usec);

#include <time.h>
int my_usleep(useconds_t Usec)

    return nanosleep(&(const struct timespec) 
      .tv_sec = Usec/100000, .tv_nsec=1000*Usec%1000000, NULL);

应该解决问题。

【讨论】:

感谢您的回复。我正在对我的代码进行一些测试,我意识到了一些事情。如果定时器间隔值大于超级循环的睡眠值,它正在工作。如果计时器提前进入,它会抑制睡眠或睡眠命令。换句话说,它取消了睡眠。我会更新上面的代码。【参考方案2】:

看来您使用的计时器库类似于 https://www.teuniz.net/Timer_code/ 提供的计时器库。如果你在那个库中打开timer.c,你会看到它使用了setitimer(ITIMER_REAL, ...)。以这种方式创建的计时器将在计时器到期时生成SIGALRM。这反过来又会从sleep()ing 唤醒您的程序。

为什么?因为,如果您阅读 sleep() 的 POSIX 规范(可在 http://pubs.opengroup.org/onlinepubs/009695399/ -> 字母索引 -> sleep() 获得),您将阅读。

sleep() 函数将导致调用线程暂停执行,直到参数 seconds 指定的实时秒数已经过去或将信号传递给调用线程及其action 是调用信号捕获函数或终止进程。

另一方面,如果您使用上述库,那么您需要准确显示您的start_timer() 函数正在做什么。否则,任何试图帮助你的人都是在黑暗中开枪。

解决方案:线程

我认为您唯一的选择是使用单独的线程 - 一个线程用于休眠的任务,另一个用于处理计时器的任务。

【讨论】:

以上是关于timer_start() 睡眠后的 C 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中的延迟/睡眠不起作用

循环,100% CPU 使用,使用睡眠不起作用?

iOS startMonitoringForRegion 在睡眠模式下不起作用(黑屏)

睡眠在pyqt4上不起作用

当 Windows 进入睡眠模式然后唤醒时 setTimeout 不起作用

当 Windows 进入睡眠模式然后唤醒时 setTimeout 不起作用