我只是使用函数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();
}
}
我做错了什么?
答案 0 :(得分:0)
您正在使用cicleProgram()
作为您的信号处理程序(尽管它的类型错误 - 它应该采用int
参数)。这意味着在您键入q
或Q
之前,您永远不会从信号处理程序返回,并且系统可能会阻止信号直到第一个信号处理程序返回。所以,你永远不会得到第二个信号 - 它被阻止了。
使用单独的信号处理函数。另请参阅What is the difference between sigaction()
and signal()
?并使用sigaction()
优先于signal()
。
并使用int main(void)
- 至少包含返回类型。即使是标准的旧版(C99),也要求当前(C11)标准。我们已经发展到21世纪;不要在20世纪C编码!
另请参阅How to avoid using printf()
in a signal handler?,了解有关在信号处理程序中可以执行的操作的信息。
我可以在那个&#34;中添加一些控件吗?为了评估信号警报并避免死锁?
原始代码存在多个问题,并未诊断出所有可能的问题。另一个问题是,如果发出警报,则没有任何内容可以再次设置警报,因此程序会等到您输入字符为止。
以下是您玩的一些实验性代码:
#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()
,但功能已经改进;它不再是信号处理程序。我在Mac OS X(基于BSD)上运行,这些系统不需要您重置信号处理函数中的signal()
处理程序。第二个函数actionProgram()
使用sigaction()
而不是signal()
。这可能不是必要的,但它给你一些东西可以看。 SA_RESTART
元素中缺少sa.sa_flags
表示read()
系统调用报告每次信号关闭时它都被中断。 signal_handler()
中的代码不使用不允许的函数调用。
示例输出(程序名称al97
):
$ ./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
$
跑步中有一些相当长的停顿,但你可以在你的机器上进行试验。您可能需要在signal()
的{{1}}函数中重新包含alarm_handler()
,并使用不同的处理程序(不会像现在一样使用cicleProgram()
)signal()
1}}。