我不是编程新手,但对Linux来说还不是新手。我正在尝试使用信号异步捕获按钮,如下所示:
根据notes on sigtimedwait(),应该阻止你想要等待的信号,然后调用sigtimedwait()。但是我从来没有看到sigtimedwait()捕捉被阻挡的信号。我已经通过几种方式运行下面的代码来查看不同场景会发生什么:
所有这些都是预期的,除了sigtimedwait()似乎没有抓住信号的事实。
我查看了类似的代码,例如this。但是我不明白特定代码是如何工作的:SIGUSR1没有被阻止,所以提高它应该立即终止程序(SIGUSR1的默认动作)。
看起来我在这里遗漏了一些东西。我究竟做错了什么?或者在工作线程中使用raise()的错误是什么?我正在使用Raspbian Stretch(Debian 9.1)在Raspberry Pi 3上运行它,可能会出现问题吗?
[我知道printf()不应该在信号处理程序中使用,但为了这个目的它可以工作]
任何帮助表示感谢,谢谢!
#include <stdio.h>
#include <stdlib.h>
#include <bcm2835.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#define PIN_BUTTON1 RPI_V2_GPIO_P1_22 // GPIO #24
// Thread function
void* check_button1(void* param)
{
while (true)
{
if (bcm2835_gpio_lev(PIN_BUTTON1) == HIGH)
{
printf("Button 1 pressed ");
raise(SIGUSR1);
}
delay(250);
}
}
// Signal handler, if applied
volatile sig_atomic_t usr_interrupt = 0;
void sync1(int sig)
{
printf("sync1 hit ... ");
usr_interrupt = 1;
}
int main(int argc, char** argv)
{
if (!bcm2835_init())
{
printf("Failed to initialize BCM2835 GPIO library.");
return 1;
}
bcm2835_gpio_fsel(PIN_BUTTON1, BCM2835_GPIO_FSEL_INPT);
sigset_t sigusr;
sigemptyset(&sigusr);
sigaddset(&sigusr, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &sigusr, NULL);
signal(SIGUSR1, sync1);
// Start the threads to read the button pin state
pthread_t th1;
pthread_create(&th1, NULL, check_button1, NULL);
// Create a two second loop
struct timespec timeout = { 0 };
timeout.tv_sec = 2;
usr_interrupt = 0;
int nLoopCount = 0;
while (true)
{
printf("Loop %d, waiting %d seconds ... ", ++nLoopCount, timeout.tv_sec);
int nResult = sigtimedwait(&sigusr, NULL, &timeout);
if (nResult < 0)
{
switch (errno)
{
case EAGAIN: printf("EAGAIN "); break; // Time out, no signal raised, next loop
case EINTR: printf("EINTR "); break; // Interrupted by a signal other than SIGCHLD.
case EINVAL: printf("EINVAL "); exit(1); // Invalid timeout
default: printf("Result=%d Error=%d ", nResult, errno); break;
}
printf("\n");
continue;
}
printf("Signal %d caught\n", nResult);
}
return 0;
}
ADDENDUM:与此同时,我通过 kill(getpid(),SIGUSR1)替换 raise(SIGUSR1)来实现此目的。很奇怪,因为according to the manual raise(x)相当于单线程程序中的 kill(getpid,x)和 pthread_kill(pthread_self() ,x)在多线程的。用 pthread_kill(pthread_self,SIGUSR1)替换 raise(SIGUSR1) 无效。如果有人能向我解释这个......