最近一直在使用SIGINT和SIGHUP等信号及其在Linux上正在进行的进程中的作用进行测试。运行以下代码返回了一些有趣的结果。
#include <signal.h> #include <stdio.h> void routine(int p){ puts("Not finishing"); sleep(2); } main(){ int i = 0; signal(SIGINT, routine); signal(SIGHUP, routine); while(1){ printf("%d \n", i++); } }
如您所见,它在无限循环中仅从0开始计数。然后,通过在其创建的进程上使用kill -SIGINT,我得到了以下信息:
如您所见,在我要求打印例程的那一行之前,程序重复了最后一个数字(而且并非总是如此)。我真的很想知道为什么。
答案 0 :(得分:1)
您很可能会偶然地避免可怕的错误。
我认为正在发生的情况是信号有时会在printf
进行格式化并将字符串格式化为输出缓冲区时中断。然后,信号处理程序中的puts
将更多字符串插入输出缓冲区。然后处理程序返回,printf
插入换行符并刷新缓冲区。
但是,如果该信号刚好在刷新整个8K输出缓冲区之前发生,将会发生什么。缓冲区位置将在末尾。然后发生puts
调用,没有意识到printf
已经在刷新和清除缓冲区了。它将puts
字符串放在哪里?一开始?在末尾?多余的数据printf
是否正在写入过程中,覆盖了puts
所添加的字符串?所有这些事情都是可能的。
缓冲的C输出不是可重入的,不能在信号处理程序中使用。