【发布时间】:2021-03-22 17:33:20
【问题描述】:
我正在学习 C 语言中的信号概念,并在构建练习程序时遇到了问题。
在下面的代码中,我试图在用户每次按下“ctrl-c”后重置SIGINT,并记录用户按下“ctrl-c”的次数。
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<setjmp.h>
void handler(int signo);
jmp_buf buf;
int int_counting = 1;
void handler(int signo)
{
signal(SIGINT, SIG_DFL);
int_counting++;
// just tried to add another "signal(SIGINT, handler)" here
// but saw the same result
longjmp(buf, 1);
}
int main()
{
if ((signal(SIGINT, handler) == SIG_ERR))
{
printf("Fail to catch the signal\n");
}
if (!setjmp(buf))
{
printf("Waiting for any signals ... \n");
}
else
{
if (!setjmp(buf)){} // to reset "setjmp" to zero
printf("Pressed 'ctrl-c' for %d times\n", int_counting);
printf("Waiting for another signal\n");
signal(SIGINT, handler);
}
while (int_counting <= 5)
{
sleep(1);
printf("Processing ...\n");
}
}
但是,在第一个信号之后,无法将其他信号发送到 handler,输出如下所示:
谁能解释一下原因?
以下是信号似乎不会被屏蔽的示例。
// Examples for SIGALRM
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
int counting = 0;
void handler(int signo)
{
printf("%d\n", counting);
while (counting < 5)
{
signal(SIGALRM, handler);
printf("%d\n", beeps);
counting++
alarm(1);
}
}
void main(void)
{
if (signal(SIGALRM, handler) == SIG_ERR)
{
printf("cannot catch SIGALRM\n");
}
alarm(1);
while (counting < 5)
{
pause();
}
return;
}
// Example for SIGQUIT
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<setjmp.h>
jump_buf buf;
void handler(int signo)
{
signal(SIQQUIT, handler);
longjmp(buf, 1);
}
int main()
{
signal(SIQQUIT, handler);
if (!setjmp(buf))
{
printf("begin ...\n");
}
else
{
print("restart ...\n");
}
while (1)
{
sleep(1);
printf("waiting for sinals ...\n");
}
}
虽然我最初的问题得到了回答,但如果有任何进一步的解释 为什么这些信号不会被屏蔽(或者请告诉我它们在 C 中是如何工作的),这将非常有帮助。
【问题讨论】:
-
恕我直言,以我的拙见,您应该首先查看此geeksforgeeks.org/signals-c-language 如果您的目标只是测试信号,那么选择一个 hello world 会更好。专注于程序的目标可以减少代码中不必要的复杂性。
-
顺便说一句,试图在信号处理程序中捕获信号是行不通的。到那时信号将处于挂起状态。这就像在中断处理程序中等待中断一样。那也可以是你的问题。
-
感谢您的建议。我已经查看了您附加的链接,但没有发现任何有用的信息......在这里我试图在
handler和main之间跳转,但我不明白为什么@987654333 中else语句中的signal(SIGINT, handler)@ 不起作用 -
@breiters 因为我不能堆叠信号,所以我不知道如何像
alarm那样迭代地运行main => handler => main => handler。或者也许我可以在SIGINT handler中发出警报并在SIGALRM handler中处理主要部分 -
@SanaeKochiya 如果您不需要在信号处理期间将信号处理程序设置为
SIG_DFL,您也可以简单地从信号处理程序返回没有longjmp。