注册后处理信号。 在信号处理函数中是否需要再次调用signal()来重新注册?
检查这个答案。 或者特别是这个环节。 基本上它取决于您的unix系统遵循的模型(BSD或系统V)。
从信号手册页中提取。
在最初的Unix系统中,当使用signal()建立的处理程序通过传递信号被调用时,信号的处置将被重置为SIG_DFL,并且系统不阻止进一步的信号实例。 System V还为signal()提供了这些语义。 这很糟糕,因为在处理者有机会重新建立自己之前,信号可能再次被传送。 此外,相同信号的快速交付可能会导致处理程序的递归调用。
BSD通过改变信号处理的语义改善了这种情况(但是,不幸的是,当用signal()建立一个处理程序时默默地改变了语义)。 在BSD上,当一个信号处理程序被调用时,信号处置没有被重置,并且在处理程序正在执行时信号的其他实例被阻止被传递。
Linux上的情况如下:
- 内核的signal()系统调用提供了System V语义。
- 默认情况下,在glibc 2和更高版本中,signal()包装函数不会调用内核系统调用。 相反,它使用提供BSD语义的标志调用sigaction(2)。 只要定义了_BSD_SOURCE特性测试宏,就会提供此默认行为。 默认情况下,_BSD_SOURCE被定义; 如果定义了_GNU_SOURCE,也可以隐式定义,当然也可以明确定义。
在glibc 2及更高版本上,如果_BSD_SOURCE特性测试宏未定义,则signal()提供System V语义。 (如果在其标准模式(-std = xxx或-ansi)之一调用gcc(1)或定义各种其他功能测试宏(如_POSIX_SOURCE,_XOPEN_SOURCE或_SVID_SOURCE),则不提供_BSD_SOURCE的默认隐式定义;请参阅feature_test_macros (7)。)- Linux libc4和libc5中的signal()函数提供了System V语义。 如果一个libc5系统包含而不是,那么signal()就提供了BSD语义。