如何暂停的信号驱动的妖主循环?

问题描述 投票:0回答:1

我工作的一个电子电话线仿真的树莓派。对于这一点,我在有此需要的功能,这就是所谓的每个20毫秒(= 50Hz时,振铃电压 - 频率的一半)的,检查电流并更新一个HW PWM的占空比。为了达到这个目标,我设置了一个信号处理程序上的计时器根据(如我把它挂到调度在纯嵌入式环境),让它做其工作。请注意,下面的代码只是为了kfocus在这个问题上缩短。

这已经工作得很好。我很惊讶,定时是如何精确保持(抖动低于10微秒,用示波器测量)。

然而,有到现在为止一个缺陷:那样工作时,实际上是无需对主回路。我不能从它返回,因为这将终止该进程。当我只是让它空循环,所有工作正常。但我想不必要地消耗CPU的负载。

我想睡觉,等待(这两者不应该再使用了,我知道),和sigsuspend。但所有这些让到报警处理程序不叫了。

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <sys/time.h>
#include <bcm2835.h>

#define PIN_PWM RPI_V2_GPIO_P1_35

bool b_Alive;

/** Signal-Handlers: ******************************************************************/

void SIG_Alarm (int signum) {
    /** Just toggle a pin for now:                                                    */
    static bool bOn;
    if (bOn) {
        bOn = 0;
        bcm2835_gpio_write(PIN_PWM, LOW);
    }else{
        bOn = 1;
        bcm2835_gpio_write(PIN_PWM, HIGH);
    }
}

void SIG_Quit (int signum) {
    /** Shutdown the bcm-library:                                                     */
    bcm2835_close();
    /** Close the sys-log handler:                                                    */
    syslog(LOG_NOTICE + LOG_DAEMON, "Received SigInt and closed.");
    closelog();
    b_Alive = false;    
}

/** Main-Function: ********************************************************************/


int main(void) {
    /** Variables:                                                                    */
    struct sigaction sa;
    struct itimerval timer;
    /** Open syslog instead: */
    openlog( "PhoneLined", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_LOCAL0 );
    /** Setup pins:                                                                   */
    if (!bcm2835_init()) return 1;
    bcm2835_gpio_fsel(PIN_PWM, BCM2835_GPIO_FSEL_OUTP);
    /** Setup signal handler for kill:                                                */
    memset(&sa, 0, sizeof (sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = &SIG_Quit;
    sigaction(SIGINT , &sa, NULL);
    sigaction(SIGQUIT, &sa, NULL);
    sigaction(SIGKILL, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    /** Setup signal handler for timer:                                               */
    memset(&sa, 0, sizeof (sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = &SIG_Alarm;
    sigaction(SIGVTALRM, &sa, NULL);
    /** Configure the timer of a start- and cycle-time of 20ms (=50Hz):               */
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = 20000;
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 20000;
    setitimer(ITIMER_VIRTUAL, &timer, NULL);
    /** Prepare main-loop:                                                            */
    b_Alive = true;
    syslog(LOG_NOTICE + LOG_DAEMON, "Sucessfully initialized.");
    /** ... and do nothing, while the timer works:                                    */
    while (b_Alive) {
        //pause(), suspend, wait or anything?
    }
    exit(EXIT_SUCCESS);
}

是否有任何线索,如何进行,没事的时候其实是在这个循环做?

c linux signals raspberry-pi3 alarm
1个回答
2
投票

至少添加volatile到您的标志的定义,或者循环将被优化器中删除(对于-O2,或更高)

(带cc -Wall -O4 -S signal.c检查)


#include <stdbool.h>
// volatile sig_atomic_t
volatile bool
        b_Alive=false;

主要():

...
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 20000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 20000;
setitimer(ITIMER_REAL, &timer, NULL);

// Prepare main-loop:            

b_Alive = true;
    syslog(LOG_NOTICE + LOG_DAEMON, "Sucessfully initialized.");
    /** ... and do nothing, while the timer works:                                    */
    while (b_Alive) {
        pause(); //, suspend, wait or anything?
    }
    exit(EXIT_SUCCESS);

而且,timertypes(从精细的手工):


   ITIMER_REAL    This timer counts down in real (i.e., wall clock) time.  At each expiration, a SIGALRM signal is generated.

   ITIMER_VIRTUAL This timer counts down against the user-mode CPU time consumed by the process.  (The measurement includes CPU time consumed by all threads in the process.)  At each
                  expiration, a SIGVTALRM signal is generated.

而且,由于pause()不占用任何CPU蜱,该定时器绝不会使用ITIMER_VIRTUAL时到期。 (也:一个不同的信号被传递)

© www.soinside.com 2019 - 2024. All rights reserved.