在C语言中,每次调用都需要重置信号处理程序吗?
我读了以下内容: 在C程序中调用信号处理程序时,其相应的信号操作设置为SIG_DFL。如果要再次处理同一信号,必须重置信号操作 但是,下面的代码一直在打印在C语言中,每次调用都需要重置信号处理程序吗?,c,C,我读了以下内容: 在C程序中调用信号处理程序时,其相应的信号操作设置为SIG_DFL。如果要再次处理同一信号,必须重置信号操作 但是,下面的代码一直在打印我收到了一个SIGHUP,没有重置它,它不会返回到它的默认处理程序 #包括 #包括 #包括 void sighup(){ //信号(SIGHUP,SIGHUP); printf(“我收到了一个SIGHUP\n”); } int main(){ 信号(SIGHUP,SIGHUP); 而(1){ 举起(叹息); 睡眠(1); } 返回0; } 一
我收到了一个SIGHUP
,没有重置它,它不会返回到它的默认处理程序
#包括
#包括
#包括
void sighup(){
//信号(SIGHUP,SIGHUP);
printf(“我收到了一个SIGHUP\n”);
}
int main(){
信号(SIGHUP,SIGHUP);
而(1){
举起(叹息);
睡眠(1);
}
返回0;
}
一个快速的谷歌搜索,您引用的段落仅适用于IBM ILE版本的signal()
函数
Linux和BSD上的signal
手册页似乎不包含此类通知,正如您所观察到的,似乎也没有表现出此类行为。您引用的一段快速谷歌搜索仅适用于IBM ILE版本的signal()
函数
Linux和BSD上的
signal
手册页似乎不包含此类通知,并且正如您所观察到的,似乎没有表现出此类行为。正如其他人所提到的,sigaction
可能会给您更多的控制
但是,您不能[不允许]从信号处理程序调用printf
。它可能会弄乱堆和stdout
流[或产生其他未指定的效果]
在信号处理程序中只能调用有限数量的函数,而不会产生灾难性/不可预测的结果[而且printf
不是其中之一]
更新:
对不起,有这方面的文章吗?信号处理器与堆有什么关系 是的,请参见
man 7信号
和[更重要的是]man 7信号安全
printf
执行malloc/free
以获取[临时]结构。可以随时调用信号处理程序
如果基本任务处于分配/释放内存的中间,将会发生什么。在线程之间,malloc/free
使用互斥锁以防止两个试图同时使用堆的线程损坏
但是,当堆处于不确定状态时,互斥不会阻止信号处理器在中间发射。 因此,你可以:
T0: enter malloc
T1: lock mutex
T2: start some allocation
T3: enter signal handler
T4: call printf
T5: call malloc
T6: change heap
T7: exit malloc
T8: exit printf
T9: exit signal handler
T10: try to finish allocation, using stale linked list pointers that are no
longer valid -- bang, bang!
标准输出的文件
结构中的值也可能出现同样的问题,正如其他人所提到的,sigaction
可以给您更多的控制
但是,您不能[不允许]从信号处理程序调用printf
。它可能会弄乱堆和stdout
流[或产生其他未指定的效果]
在信号处理程序中只能调用有限数量的函数,而不会产生灾难性/不可预测的结果[而且printf
不是其中之一]
更新:
对不起,有这方面的文章吗?信号处理器与堆有什么关系
是的,请参见man 7信号
和[更重要的是]man 7信号安全
printf
执行malloc/free
以获取[临时]结构。可以随时调用信号处理程序
如果基本任务处于分配/释放内存的中间,将会发生什么。在线程之间,malloc/free
使用互斥锁以防止两个试图同时使用堆的线程损坏
但是,当堆处于不确定状态时,互斥不会阻止信号处理器在中间发射。
因此,你可以:
T0: enter malloc
T1: lock mutex
T2: start some allocation
T3: enter signal handler
T4: call printf
T5: call malloc
T6: change heap
T7: exit malloc
T8: exit printf
T9: exit signal handler
T10: try to finish allocation, using stale linked list pointers that are no
longer valid -- bang, bang!
同样的问题也可能发生在标准输出的文件
结构中的值上。
您引用的任何书籍或文章都是非常正确的。。。对于某些编译环境
一般来说,如果一个信号处理函数可能被同一个信号中断,这将是一个坏主意。这将导致递归调用信号处理程序,并使编写信号处理程序变得更加困难
因此,这是不允许的,至少在默认情况下是不允许的。但是Posix允许两种完全不同的机制来防止嵌套处理程序调用。当使用信号处理函数作为参数调用了signal
(即既不是SIG_-DFL
也不是SIG_-IGN
)并且引发了相应的信号SIG
:
…是否等效于:
signal(sig, SIG_DFL);
执行或实现阻止某些实现定义的信号集(至少包括sig)发生,直到当前信号处理完成。(来自的Posix说明。)
这两个选项都会在信号处理程序执行期间阻塞信号,但第一个选项不会恢复信号处理程序,而第二个选项会在信号处理程序未正常返回时(例如通过longjmp
或execve()
)使信号保持阻塞状态
如果您编写的程序可能运行在不同的操作系统上,或者甚至运行在具有不同编译器的同一操作系统上,或者运行在具有相同编译器但具有不同编译器选项的同一台计算机上,那么您不能指望其中一种行为。而且也没有便携式的方法来判断发生了哪一次
因此,signal
不应用于安装信号处理程序;按照Posix的建议,使用sigaction
:
sigaction()
功能为控制信号提供了更全面、更可靠的机制;新应用程序应该使用sigaction()
而不是signal()
。
(来自同一Posix页面的“应用程序使用”部分。请注意,此建议已有20年历史;“新应用程序”应为interpre
void sig_handler(int signum)
{
signal(signum, sig_handler);
…the rest of the handler…
}