根据各种参考资料,我对Linux中的信号有以下主观定义:“用于通知进程某个特定事件发生的触发器。该事件可能是软件异常。此外,信号也可用于IPC机制。” 我的问题是:
- 我认为只有异常(软件中断)通过信号被通知。那硬件中断呢?
- 信号的各种来源是什么?在我看来,内核似乎总是信号的来源。(除了用于IPC时)
- 信号处理程序和ISR之间的区别是什么?
- 信号阻塞和中断屏蔽之间的区别是什么?
中断可以被看作是CPU和操作系统内核之间通信的一种手段。信号可以被看作是操作系统内核与操作系统进程之间通信的一种手段。
中断可能由CPU(例如:除以零,页面错误等异常情况),设备(硬件中断--例如:输入可用性)或CPU指令(陷阱--例如:系统调用,断点)发起。最终由CPU管理它们,它“中断”当前任务,并调用由操作系统内核提供的ISR /中断处理程序。
信号可能由操作系统内核(例如:SIGFPE、SIGSEGV、SIGIO)或进程(kill())发起。最终由操作系统内核管理它们,将它们传递给目标线程/进程,调用通用操作(忽略、终止、终止并转储核心)或进程提供的信号处理程序。
通过利用硬件中断也可以实现多任务处理。所有驱动程序通常都是通过解释中断来工作的。
Signals被用于进程间通信。在Linux守护进程中,SIGHUP信号是常见的行为,用于重新加载配置文件,这一点备受系统管理员的喜爱和厌恶。当你修改例如Apache配置时,进程不会自动使用新的配置文件。您可以终止并重新启动该过程,但这意味着您的HTTP服务器将在4-5秒内无法访问。因此,您可以使用“killall -HUP apache”命令。这将调用Apache进程中的子例程,使其重新读取其配置文件。信号可以来自进程本身(SIGABRT),来自内核(SIGSEGV等),也可以来自其他进程,例如shell(ctrl-z,ctrl-c,ctrl- \,...)或来自kill。但是它们也可以通过使用kill libc函数来自任何其他程序:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
主要区别在于ISR位于内核空间,并且必须考虑到整个计算机在其执行期间被冻结。这意味着它们可能会中断任何进程和内核中的任何内容。它们还会“停止世界”。在处理中断时,不会发生任何其他事情。因此,如果中断处理程序等待某些东西,则机器将冻结。如果中断处理程序进入循环,则您唯一的选择是重新启动机器。
ISR真的很难正确处理。它们有许多理论,在Linux上,它们具有上半部分和下半部分部分,具有各种优先级处理、特殊内存分配等,是一个雷区。在ISR中向错误方向迈出一步就会导致机器崩溃。 ISR中的错误会导致数据丢失,甚至可能导致硬件故障。实际上,根据经验,仅引起对ISR中可能计划做错事情的怀疑立即会导致完全不可预测的机器行为。
在ISR中无法使用任何内核设施。打开文件,忘掉它。分配内存,忘掉它。调用内核的任何其他部分,忘掉它(只有很少数的例外)。列表还在继续。
Signals只是在特定进程中调用的函数。信号可以阻塞(例如ctrl-z),这将阻止该进程继续执行,但例如您的shell会话仍然会响应。进程需要考虑到程序的任何部分都可能被打断,但它仍然是正常的用户空间。您可以阻塞、循环、打开文件、分配内存等等。