SIGALRM报警只跳过getchar一次
我只是使用函数SIGALRM报警只跳过getchar一次,c,C,我只是使用函数alarm跳过getchar,但有些事情进展不顺利,因为它只跳过一次,我希望它无限期地跳过 例如: #include <signal.h> int duration = 2; main() { cicleProgram(); } void cicleProgram(){ while(opcion != 'q' && opcion != 'Q'){ signal(SIGALRM, (void*)cicleProgram);
alarm
跳过getchar
,但有些事情进展不顺利,因为它只跳过一次,我希望它无限期地跳过
例如:
#include <signal.h>
int duration = 2;
main() {
cicleProgram();
}
void cicleProgram(){
while(opcion != 'q' && opcion != 'Q'){
signal(SIGALRM, (void*)cicleProgram);
alarm(duration);
opcion = getchar();
}
}
#包括
int持续时间=2;
main(){
循环程序();
}
无效循环程序(){
而(opcion!='q'&&opcion!='q'){
信号(SIGALRM,(void*)循环程序);
警报(持续时间);
opcion=getchar();
}
}
我做错了什么?您正在使用
cicleProgram()
作为信号处理程序(尽管它的类型错误-它应该使用int
参数)。这意味着您在键入q
或q
之前不会从信号处理程序返回,并且系统可能会在第一个信号处理程序返回之前阻止信号。所以,你永远不会得到第二个信号——它被阻塞了
使用单独的信号处理函数。另请参见并优先使用sigaction()
,而不是signal()
并将intmain(void)
-至少与返回类型一起使用。即使是旧的(C99)版本的标准也需要这样做,更不用说当前的(C11)标准了。我们已经进入21世纪;不要用20世纪的C语言编写代码
有关在信号处理程序中可以执行的操作的信息,请参见
我是否可以在“while”中添加一些控件,以评估信号警报并避免死锁 原始代码存在多个问题,并不是所有可能的问题都被诊断出来。另一个问题是,如果触发了警报,则无法再次设置警报,因此程序将陷入等待状态,直到您键入一个字符 下面是一些您可以使用的实验代码:
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static int duration = 2;
static volatile sig_atomic_t alarm_fired = 0;
static void alarm_handler(int signum)
{
//signal(SIGALRM, alarm_handler);
write(STDOUT_FILENO, "Signalled!\n", 11);
alarm_fired = signum;
alarm(duration);
}
static void cicleProgram(void)
{
int opcion = 0;
while (opcion != 'q' && opcion != 'Q')
{
signal(SIGALRM, alarm_handler);
alarm(duration);
if ((opcion = getchar()) == EOF)
clearerr(stdin);
if (alarm_fired)
{
alarm_fired = 0;
printf("Alarm!\n");
}
printf("c = %d\n", opcion);
}
}
static void actionProgram(void)
{
struct sigaction sa = { 0 };
sa.sa_handler = alarm_handler;
sa.sa_flags = 0;
sigfillset(&sa.sa_mask);
sigaction(SIGALRM, &sa, 0);
int opcion = 0;
while (opcion != 'q' && opcion != 'Q')
{
alarm(duration);
if ((opcion = getchar()) == EOF)
clearerr(stdin);
if (alarm_fired)
{
alarm_fired = 0;
printf("Alarm!\n");
}
printf("c = %d\n", opcion);
}
}
int main(void)
{
printf("Using signal (q to quit):\n");
cicleProgram();
printf("Using sigaction (q to quit):\n");
actionProgram();
return 0;
}
在运行过程中有一些相当长的暂停,但您可以在您的机器上进行试验。您可能需要在
cicleProgram()
的alarm\u handler()
函数中重新包含signal()
,并在actionProgram()
后定义opcion
中使用不同的处理程序(不像现在那样使用signal()
)。您已经将circleProgram设置为SIGALRM的信号处理程序。当发出SIGALRM时,操作系统似乎认为在信号处理程序返回之前,您的程序正在忙于处理该SIGALRM,因此它不会向您发送另一个SIGALRM。您也可能处于死锁状态-您只能使用信号处理程序中的函数。页面向下-有一个POSIX需要异步信号安全的函数列表。在您的实现中,当发送报警信号时,您可能处于getchar()
等待输入状态,这会导致另一个circleprogram()
调用在正常程序流之外异步启动。它尝试调用getchar()
,但原始调用已锁定输入流-死锁。因此,我是否可以在“while”中添加一些控件以评估信号警报并避免死锁?谢谢欢迎来到堆栈溢出。请注意,在这里说“谢谢”的首选方式是投票选出好的问题和有用的答案(一旦你有足够的声誉这么做),并接受对你提出的任何问题最有用的答案(这也会给你的声誉带来一点提升)。请参阅页面,我是否可以在“while”中添加一些控件,以评估信号警报并避免死锁?谢谢谢谢!在我证明你的代码之后,我会更仔细地看看会发生什么,真的,thanksit工作得非常好!我得到了我需要的参考资料,所以它非常有用!谢谢
$ ./al97
Using signal (q to quit):
Signalled!
Signalled!
Signalled!
Signalled!
WonderfulSignalled!
Alarm!
c = 87
c = 111
c = 110
c = 100
c = 101
c = 114
c = 102
c = 117
c = 108
c = 10
Signalled!
Signalled!
q
Alarm!
c = 113
Using sigaction (q to quit):
c = 10
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
ASignalled!
Alarm!
c = -1
lso workingSignalled!
Alarm!
c = -1
c = 65
c = 108
c = 115
c = 111
c = 32
c = 119
c = 111
c = 114
c = 107
c = 105
c = 110
c = 103
c = 10
qSignalled!
Alarm!
c = -1
c = 113
$