我正在学习用C语言为Linux系统编写一个信号处理程序,下面是我的代码:
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void sig_handler(int signum){
//Return type of the handler function should be void
printf("\nInside handler function\n");
}
int main(){
signal(SIGINT,sig_handler); // Register signal handler
for(int i=1;;i++){ //Infinite loop
printf("%d : Inside main function\n",i);
sleep(1); // Delay for 1 second
}
return 0;
}
我的问题是,为什么当我按下Ctrl+C两次时,程序就停止了?难道不是每次我按下Ctrl+C时,信号处理程序都运行,所以程序应该永远运行下去吗?
实际上,这是我的输出,信号处理程序只在第一次Ctrl+C时调用,而不是第二次:
2条答案
按热度按时间bxpogfeg1#
我的问题是,为什么当我按两次Ctrl+C时,程序停止了?
未定义的行为:
您的代码调用了未定义的行为,因为它调用了非异步信号安全的函数(
printf
)。¹来自C11:
如果信号不是作为调用中止或引发函数的结果而发生,则如果信号处理程序不是通过向声明为volatile sig_atomic_t的对象赋值而引用具有静态或线程存储持续时间的不是无锁原子对象的任何对象,或者信号处理程序调用标准库中的除中止函数之外的任何函数,_Exit函数、quick_exit函数或第一个参数等于导致调用处理程序的信号所对应的信号编号的信号函数。
根据C标准,您只能调用:
安全地藏在信号处理器里。
然而,POSIX标准规定了更多的函数,所以你可以有
write()
,但不能有printf()
。[1]- * async-signal-safe函数是可以从信号处理程序中安全调用的函数。(Linux手册页)*
gcuhipw92#
发生这种情况是因为在函数
sig_handler()
* 中,您 * 定义的函数没有调用exit()
或任何类似的函数。如果您只在该函数中添加exit(1);
,它将在第一个signint信号处终止。此外,在信号处理程序中调用printf()
不是一个安全的调用async-signal-safe,这要归功于Andreas Wenzel。