I'm now learning signals in computer system and I've stuck with a problem. There is a code given below;
int i = 0;
void handler(int s) {
if(!i) kill(getpid(), SIGINT);
i++;
}
int main() {
signal(SIGINT, handler);
kill(getpid(), SIGINT);
printf("%d\n", i);
return 0;
}
And the solution says that the possible output should be 0, 1, or 2. I understand that these are possible, but why not 3, 4 or others?
For example, we send SIGINT in the main function. Handler gets SIGINT signal, and send SIGINT as it is zero. Before it proceeds to the increment code, handler might be able to listen to SIGINT signal and send SIGINT signal one more time as it is executed before the increment code (i = 0) - loops again, again - and it might print out 3, 4, 5, or even bigger numbers.
答案 0 :(得分:2)
历史上,关于信号如何工作的许多细节都发生了变化。 例如,在最早的变体中,当调用处理程序时,信号的处理恢复为默认值,并且处理程序必须重新建立自身。在这种情况下,从处理程序发送信号会终止进程。
目前,通常情况是在为特定信号调用处理程序时,该信号被阻止。这意味着当时不会调用处理程序,但是当信号被解除阻塞时将调用它。由于无法记录信号的发送频率,因此其中一些可能会“丢失”。
见POSIX <signal.h>
,
Signal Concepts,
signal()
和sigaction()
。
答案 1 :(得分:1)
这是因为信号通常在交付时被阻止。因此,在您的示例中,kill
内的handler
无法在该位置生效。您必须等待从处理程序返回才能再次捕获信号。
理论上,您可以获得0,因为在传递信号时未指定。因此,您可能会在主要信号中抛出信号,并在交付之前执行printf
。
你可以得到1,因为通常信号传递发生在系统调用结束或量子开始或结束时。因此,在您的情况下,在发送信号后,您返回用户空间并传递信号,这将产生处理程序的执行,递增i
,然后返回到正常的执行流,然后打印。
你可以拥有2,因为从处理程序返回时,信号被解除阻塞,然后第二次传递。这是更常见的情况。
您不能超过2,因为您为此设置了条件。当i!=0
你不再发出信号时,它就不会被抛出超过2次。
请注意,没有&#34;递归&#34;这里...