目录
1、不可靠信号与可靠信号
1.1、不可靠信号
1.2、可靠信号
2、实时信号和非实时信号
2.1、非实时信号
2.2、实时信号
在Linux系统中,信号可以从两个不同的角度进行分类:一是从可靠性方面,将信号分为可靠信号与不可靠信号;二是从实时性方面,将信号分为实时信号与非实时信号。
在 Linux 系统下使用"kill -l"命令可查看到所有信号,如下所示:
图中,信号编号在1到31之间的信号被定义为不可靠信号(非实时信号)。这些信号主要继承自早期的UNIX系统,使用了最初设计的简单信号机制。在这种机制中,如果一个信号在进程处理另一个相同信号时到达,该信号可能会被丢失,从而导致进程错过某些事件。信号编号在34到64之间的信号被定义为可靠信号(实时信号)。与不可靠信号不同,可靠信号支持排队处理,即使多个相同信号在处理过程中到达,它们也不会被丢失,而是按照到达顺序依次处理。
值得注意的是,可靠信号(实时信号)并没有像不可靠信号那样的具体名称,而是采用了相对编号的方式来表示。这些信号使用SIGRTMIN+N
或SIGRTMAX-N
的形式进行表示,其中:
SIGRTMIN
是可靠信号(实时信号)的最小编号,通常为34。SIGRTMAX
是可靠信号(实时信号)的最大编号,通常为64。
因此,SIGRTMIN+1
代表编号为35的可靠信号(实时信号),SIGRTMAX-1
代表编号为63的可靠信号(实时信号)。
1、不可靠信号与可靠信号
1.1、不可靠信号
早期UNIX系统中的信号机制被称为不可靠信号,Linux的信号机制基本上继承自早期UNIX系统。所以信号机制设计相对简单,虽然实现了基本的进程间通信功能,但在实际应用中暴露出一些显著问题。
其主要问题包括:
-
信号处理后恢复默认行为
在早期的UNIX中,进程每次处理完信号后,系统会自动将该信号的处理方式恢复为默认操作。这意味着,如果用户希望持续使用自定义的信号处理函数,就需要在信号处理函数的末尾再次调用signal()
函数重新绑定处理函数。这种机制增加了编程的复杂性,并且容易导致程序员在忽略这个步骤时发生错误。 -
信号可能丢失
另一个更严重的问题是不可靠信号可能会丢失。当进程正在处理一个信号时,如果相同类型的另一个信号到达,第二个信号可能会被直接丢弃,导致进程错过了重要的事件。这在关键任务应用中尤其危险。
虽然Linux仍然支持不可靠信号机制,但对其进行了改进。Linux修复了在信号处理函数执行后必须手动重新绑定处理函数的问题。在现代Linux系统中,一旦信号处理函数被绑定,除非显式更改,否则它将一直保持有效。
然而,信号丢失问题仍然存在。这意味着,在处理不可靠信号时,如果在信号处理期间有相同信号再次到达,该信号可能无法被捕获。
1.2、可靠信号
为了克服不可靠信号的缺陷,Linux引入了可靠信号机制。可靠信号支持排队,即使进程在处理某个信号时有新的信号到达,这些信号也不会丢失,而是被加入队列,待当前信号处理完成后再依次处理。
Linux还引入了新的信号发送函数sigqueue()
和信号绑定函数sigaction()
,进一步增强了信号处理的灵活性和可靠性。sigqueue()
不仅可以发送信号,还可以附带一个整数值或指针,传递额外的信息。sigaction()
则允许更精细地控制信号的行为,替代了传统的signal()
函数。
2、实时信号和非实时信号
Linux信号的另一种分类方式是根据实时性来区分为实时信号与非实时信号。
2.1、非实时信号
非实时信号指的是传统的、不支持排队的信号。这类信号在早期的UNIX系统中得以引入,信号编号一般在1到31之间。这些信号在处理时没有严格的顺序保证,并且如果在处理某个信号时有相同类型的新信号到达,后者可能会被忽略或丢失。因此,这类信号被称为不可靠信号。
2.2、实时信号
实时信号是为了解决非实时信号在处理可靠性方面的不足而引入的。实时信号的一个显著特点是它们支持排队,即使在处理某个信号期间有新的相同类型的信号到达,这些信号也不会被丢弃,而是按照到达的顺序依次处理。这样,实时信号保证了多个信号都能被正确接收和处理,因此它们被称为可靠信号。
在实际编程中,开发者应当根据应用需求选择合适的信号类型。对于简单的进程间通信或用户交互,标准的非实时信号可能已经足够。而对于需要保证信号处理顺序且不能丢失的重要任务,使用可靠信号或实时信号是更好的选择。