gpt4 book ai didi

c - 使用C中的信号,如何在定时器结束时停止和继续程序

转载 作者:行者123 更新时间:2023-11-30 15:08:59 25 4
gpt4 key购买 nike

我正在开发一个在 Raspberry-Pi (linux) 上运行的程序,它从 GPS 模块获取数据并进行处理。

现在,该程序以 while(1) 循环为中心,该循环获取 GPS 数据并对其进行处理(数据以 GPS 模块的频率传输)。

但是,我知道 while(1) 并不是一个非常节能的解决方案(这个 RPi 稍后将安装在无人机上)。

我想设置一个计时器,只有当计时器结束时,程序才会获取GPS数据。理想情况下,程序将完全停止,直到计时器结束,这样 CPU 就不会在其上浪费时间/精力。

How can I do the above mentioned, if SIGSTOP signal is not allowed in sigaction() calls ?

void timer_handler(int signum){
/* what can I do to make a program stop and coninue,
so that no CPU cycles are devoted to this program until
the timer is elapsed ? (SIGSTOP is not allowed) */
}

int main(int argc, char** argv){

struct sigaction sigAct;
struct itimerval timer;
sa.sa_handler = &timer_handler;

// SIGALRM is only a place holder here..
sigaction(SIGALRM, &sigAct, NULL);

/* Here would be some timer.it_value, timer.it_interval stuff,
setting it to some arbitrary time */

setitimer(ITIMER_REAL, &timer, NULL);

/* Main program loop here */
while(1){
// process GPS data.
// instead of while(1), I'd like this loop to run only when
// the timer ends.
}

}

最佳答案

在循环中,只需调用 pause()。它会阻塞并且仅在收到信号时返回,因此您可以运行代码,再次循环并重复。您需要一个信号处理程序来阻止 SIGALRM 终止您的程序,但它不必执行任何操作,您只需将函数体留空即可。

例如:

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>

void timer_handler(int signum)
{
(void) signum; /* Avoids warning for unused argument */
}

int main(void)
{
struct sigaction sa;
sa.sa_handler = timer_handler;
sa.sa_mask = 0;
sa.sa_flags = 0;
sigaction(SIGALRM, &sa, NULL);

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

while ( 1 ) {
pause();
printf("Timer expired - get GPS data.\n");
}

return 0;
}

产量输出:

paul@horus:~/src/sandbox$ ./alarm
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
^C
paul@horus:~/src/sandbox$

这是一个相当粗糙的解决方案。如果代码有时可能需要比计时器间隔更长的时间来运行,那么事情就会变得不可靠,有时您可能会跳过信号。您可能关心也可能不关心这一点。对于更复杂的方法,您可以阻止接收 SIGALRM,然后使用信号掩码调用 sigsuspend() 来解锁它,因为知道解锁和等待是安全的。因为信号将是一个原子操作。下面是该方法的一个示例:

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>

void timer_handler(int signum)
{
static const char msg[] = "Handler was called.\n";
write(STDIN_FILENO, msg, sizeof(msg) - 1);
(void) signum;
}

int main(void)
{
struct sigaction sa;
sa.sa_handler = timer_handler;
sa.sa_mask = 0;
sa.sa_flags = 0;
sigaction(SIGALRM, &sa, NULL);

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

sigset_t old_mask, block_mask;
sigemptyset(&block_mask);
sigaddset(&block_mask, SIGALRM);
sigprocmask(SIG_BLOCK, &block_mask, &old_mask);

sleep(3); /* To demonstrate signal handler won't be
called until sigsuspend() is called, timer
is firing every second while we're sleeping */

while ( 1 ) {
sigsuspend(&old_mask);
printf("Timer expired - get GPS data.\n");
}

return 0;
}

输出:

paul@horus:~/src/sandbox$ ./alarm2
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
^C
paul@horus:~/src/sandbox$

为了简洁起见,在上面的示例中省略了错误检查,但是您的代码当然应该在每个系统调用中包含它。

关于c - 使用C中的信号,如何在定时器结束时停止和继续程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36953010/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com