44

根据各种参考资料,我对Linux 中信号的主观定义是“用于通知进程发生特定事件的触​​发器。这里的事件可能是指软件异常。此外,信号也可能用于 IPC 机制。 " 我的问题是

  • 我认为只有异常(软件中断)是通过信号通知的。硬件中断的情况呢?
  • 信号的各种来源是什么?在我看来,内核始终是信号的来源。(用于 IPC 时除外)
  • 信号处理程序和 ISR 之间的区别?
  • 信号阻塞和中断屏蔽的区别?
4

3 回答 3

112

中断可以看作是 CPU 和 OS 内核之间的一种通信方式。信号可以看作是操作系统内核和操作系统进程之间的一种通信方式。

中断可能由 CPU(异常 - 例如:除零、页面错误)、设备(硬件中断 - 例如:输入可用)或 CPU 指令(陷阱 - 例如:系统调用、断点)启动。它们最终由 CPU 管理,它“中断”当前任务,并调用 OS 内核提供的 ISR/中断处理程序。

信号可以由操作系统内核(例如:SIGFPE、SIGSEGV、SIGIO)或进程(kill())发起。它们最终由操作系统内核管理,将它们传递给目标线程/进程,调用通用操作(忽略、终止、终止和转储核心)或进程提供的信号处理程序。

于 2012-11-14T14:29:23.113 回答
60

我认为只有异常(软件中断)是通过信号通知的。硬件中断的情况呢?

从哪里开始?有很多不同的情况。请记住,中断是调用 CPU 的硬件。中断本质上由“需要注意的硬件”和一个介于 0 到 255 之间的数字组成。信号类似但有 2 个参数:目标进程 ID 和一个 int(32 位或 64 位,取决于架构)。硬件中断总是在内核空间处理,而信号只是用户空间的东西。内核出于各种原因使用硬件中断。

与信号无关的硬件中断的一个示例是 VM 子系统。您知道在现代操作系统上,您可以分配比系统上实际存在的内存更多的内存。那么这是如何工作的呢?好吧,它通过利用硬件中断来工作。当您分配内存时,内核会记下它,但实际上根本不做任何事情。然后,当你尝试访问分配的内存时,cpu 会报错“但是这个内存不存在”,这会产生一个硬件中断。内核将查看它的注释,发现您确实请求了该内存,清除一些它有空闲的内存,并告诉 cpu 将该内存“映射”到预期的位置。

多任务处理也是通过利用硬件中断来实现的。所有驱动程序通常通过解释中断来工作。

信号用于进程之间的通信。linux 守护进程在 SIGHUP 上重新加载其配置的常见行为是非常“信号-y”的东西,受到各地系统管理员的喜爱和憎恨。例如,当您修改 apache 配置时,该过程不会自动开始使用新配置。您可能会终止并重新启动该过程,但这意味着您的 http 服务器将在 4-5 秒内停止运行。因此,您可能会“killall -HUP apache”。这将在 apache 进程中调用一个子例程,这将使它重新读取它的配置文件。

进程挂起是通过信号 (ctrl-z)、进程中断 (ctrl-c)、进程退出 (ctrl-)、终端断开连接 (sighup) 来实现的……更完整的列表可以在这里找到:http://en .wikipedia.org/wiki/Unix_signal

一个结论可能是它们有点相似,但它们在不同的级别上运行:硬件中断是,嗯,硬件需要注意,而最低级别的软件需要。通常内核处理所有硬件,并且通知进程在某种程度上独立于硬件中断。对于许多信号,提供了默认处理(例如 ctrl-z、ctrl-c、...),对于其他信号,实现非常依赖于应用程序(例如 SIGHUP)。

说到信号,这些只是软件定义的。他们做任何你想让他们做的事,而且 linux 提供了方便的方法来调用这些子例程。在某些情况下,内核可能会调用一个信号例程(例如 SIGSEGV、SIGCHILD、...),但它几乎不涉及硬件。它们只是在应用程序中触发特定例程的便捷方式。

曾经有一个特殊情况:DOS 21h 中的“OS”中断。这不再使用(尽管仍然有效),但想法是这样的。程序可以触发特定的中断来要求内核执行特定的操作。系统调用的操作(打开文件,关闭套接字,你有什么)。正如我所说,有趣,但不再真正使用。

信号的各种来源是什么?在我看来,内核始终是信号的来源。(用于 IPC 时除外)

信号来自进程本身 (SIGABRT)、内核 (SIGSEGV, ...) 或来自其他进程,例如 shell (ctrl-z, ctrl-c, ctrl-\, ...) 或从杀。但是它们可以通过使用 kill libc 函数来自任何其他程序:

   #include <sys/types.h>
   #include <signal.h>

   int kill(pid_t pid, int sig);

信号处理程序和 ISR 之间的区别?

主要区别在于 ISR 存在于内核空间中,并且必须考虑到整个计算机在执行期间被冻结。这意味着他们可以中断任何进程,以及内核中的任何内容。他们还“阻止了世界”。在处理中断时,不会发生其他任何事情。因此,如果中断处理程序等待某些东西,机器就会冻结。如果中断处理程序进入循环,您唯一的选择是重新启动机器。

ISR 真的很难做到正确。关于它们有很多理论,在 linux 上它们有上半部分和下半部分,具有各种优先级处理、特殊内存分配……这是一个雷区。在 ISR 中朝着错误的方向迈出一步会杀死机器。ISR 中的错​​误会导致数据丢失,甚至可能导致彻底的硬件故障。事实上,从经验来看,仅仅怀疑你可能计划在 ISR 中做错事会立即导致完全不可预测的机器行为。

您不能在 ISR 中使用任何内核工具。打开一个文件,忘记它。分配内存,算了。调用内核的任何其他部分,忘记它(有一些,但只有少数例外)。名单还在继续。

信号只是被调用的特定进程中的函数。信号可能会阻塞(例如 ctrl-z),这将阻止进程继续进行,但例如您的 shell 会话仍会响应。该过程需要考虑到程序的任何部分当然可能已被中断,但它仍然是正常的用户空间。你可以阻塞,你可以循环,你可以打开文件,分配内存,......任何你想要的。

信号阻塞和中断屏蔽的区别?

它们非常相似。除了信号阻塞是在每个进程的基础上完成的。在这两种情况下都有不可阻塞的信号,并且有一个 NMI(不可屏蔽中断)(两者都表示严重错误)。

最后,信号和中断正在向内核或特定进程发送一个数字。信号阻塞和中断屏蔽只是意味着告诉系统忽略特定数字。

一个区别是中断屏蔽是在硬件中实现的。

于 2012-11-21T11:25:24.527 回答
2

信号和中断的行为方式非常相似。不同之处在于信号发生在进程(位于虚拟环境中),而异常是系统范围的。

CPU 将某些故障标记为异常,然后映射到内核传递给进程的信号。内核可以选择对进程隐藏任何异常(例如,对未映射内存的访问通过分页静默修复)。

硬件中断只是一种异常,内核可能会选择将其映射到信号(例如,如果您使用alarm(2))。

内核生成信号以响应各种事件,其中包括异常、I/O 完成、显式用户空间请求……

信号处理程序的行为类似于 ISR——它们可以随时被调用,因此它们不能对程序的状态做出任何假设,就像 ISR 一样——阻塞信号在虚拟地址空间中的行为方式与屏蔽中断相同在物理机上。

于 2012-11-12T10:35:22.407 回答