什么时候处理信号?
When Are Signals Handled?
我阅读了:
Signals are handled only when the receiving process has returned
from kernel mode to user mode.
但这对我来说没有意义,为什么?
理论上,假设进程 A 正在 运行ning 并且它向进程 B 发送了一个信号,当进程 B 启动时 运行ning 它可能永远不会 运行 在内核模式下那些永远不会查看信号并处理它。
但是,在现实世界中,信号几乎是即时处理的(至少根据我自己的观察),这怎么可能,因为我看到了一个明显的矛盾?
Theoretically, let's say process A is running and it sent a signal to process B, When process B starts running it might never run in kernel mode those never see the signal and handle it.
Linux是一个preemptive multitasking operating system. This means that the kernel gives every process a time slice and the CPU will receive a hardware interrupt有规律的时间间隔,这会return它进入内核模式,这样内核就可以,例如,给一个时间片给一个不同的过程。
因此,您描述的情况(进程将运行 永远处于用户模式而永远不会进入内核模式)永远不会出现在诸如Linux 的抢占式多任务操作系统中。
But that doesn't make sense to me, why?
信号必须在用户模式和被信号进程的进程上下文中处理,因此在进程发出系统调用(或执行另一个进程的线程)。此外,由于许多系统调用的原子性,只有中断系统调用来处理信号的机会,或者在系统调用完成后处理它们。您只保证信号处理程序将在 在 任何其他进程的用户代码之前执行,但它们不是瞬时的(好吧,它们是,但仅从进程的角度来看, 不是来自系统)
但最重要的原因是第一个:来自内核模式接口的return有特殊的代码来执行与[=36之前的信号相关联的信号处理程序=]ing 来自系统调用,但由于这必须在用户模式下执行,因此没有其他有效的方法来切换上下文、执行用户代码,然后 return 返回到正在执行的内核代码。这也可能会引发一系列安全问题(一个进程迫使内核调度超过允许的进程,因为它附加了很多信号处理程序)这段代码必须区分执行的内核模式是否是一个同步调用(一些系统调用由进程执行)或一些异步事件(硬件中断),因为用户代码必须模拟来自系统调用的 return(具有 returning 值 and/or errno
设置)或来自中断的 return(必须在中断之前保留所有寄存器和标志)此代码通常通过在切换到用户模式和 returning.
有一种特殊情况,其中进程被硬件中断(例如时钟节拍)中断,中断用户模式执行代码,并检测到挂起信号。然后,在 return 返回用户代码之前,需要一个特殊的代码序列并将其安装在用户进程的堆栈中,以执行信号处理程序并发出中断-return 代码(这意味着一个特殊的机器执行信号处理程序的代码序列,然后将系统 returns 之前的 cpu 状态完全恢复为用户进程在时钟节拍之前正在做的事情)以应对中断到来的情况在一些合理的任务中间(异步中断可以在任何时间点,在任何用户代码机器指令之间)
最后,想象一个进程,由于系统负载已被换出到磁盘并且没有图像可用于 运行 代码(甚至信号处理程序代码已被换出)你如何执行如果没有数据结构或进程代码准备就绪,则信号处理程序 运行?
内核使用户代码执行信号处理程序的方式是调整进程堆栈以强制(在 return 从 syscal/interrupt 上)调用信号处理程序,然后恢复完整的 cpu 状态(因为它是从硬件中断完成的)所以进程可以继续执行机器指令,就好像两者之间没有发生任何事情一样。这是在 完成 kernel-mode/user-mode 开关之后完成的,因此唯一可行的做法就是调整堆栈。 Linux,就像 BSD 或所有其他 unix 风格一样,将此代码安装在进程映像中,以便它在每个用户模式进程中可用。
我阅读了:
Signals are handled only when the receiving process has returned from kernel mode to user mode.
但这对我来说没有意义,为什么?
理论上,假设进程 A 正在 运行ning 并且它向进程 B 发送了一个信号,当进程 B 启动时 运行ning 它可能永远不会 运行 在内核模式下那些永远不会查看信号并处理它。
但是,在现实世界中,信号几乎是即时处理的(至少根据我自己的观察),这怎么可能,因为我看到了一个明显的矛盾?
Theoretically, let's say process A is running and it sent a signal to process B, When process B starts running it might never run in kernel mode those never see the signal and handle it.
Linux是一个preemptive multitasking operating system. This means that the kernel gives every process a time slice and the CPU will receive a hardware interrupt有规律的时间间隔,这会return它进入内核模式,这样内核就可以,例如,给一个时间片给一个不同的过程。
因此,您描述的情况(进程将运行 永远处于用户模式而永远不会进入内核模式)永远不会出现在诸如Linux 的抢占式多任务操作系统中。
But that doesn't make sense to me, why?
信号必须在用户模式和被信号进程的进程上下文中处理,因此在进程发出系统调用(或执行另一个进程的线程)。此外,由于许多系统调用的原子性,只有中断系统调用来处理信号的机会,或者在系统调用完成后处理它们。您只保证信号处理程序将在 在 任何其他进程的用户代码之前执行,但它们不是瞬时的(好吧,它们是,但仅从进程的角度来看, 不是来自系统)
但最重要的原因是第一个:来自内核模式接口的return有特殊的代码来执行与[=36之前的信号相关联的信号处理程序=]ing 来自系统调用,但由于这必须在用户模式下执行,因此没有其他有效的方法来切换上下文、执行用户代码,然后 return 返回到正在执行的内核代码。这也可能会引发一系列安全问题(一个进程迫使内核调度超过允许的进程,因为它附加了很多信号处理程序)这段代码必须区分执行的内核模式是否是一个同步调用(一些系统调用由进程执行)或一些异步事件(硬件中断),因为用户代码必须模拟来自系统调用的 return(具有 returning 值 and/or errno
设置)或来自中断的 return(必须在中断之前保留所有寄存器和标志)此代码通常通过在切换到用户模式和 returning.
有一种特殊情况,其中进程被硬件中断(例如时钟节拍)中断,中断用户模式执行代码,并检测到挂起信号。然后,在 return 返回用户代码之前,需要一个特殊的代码序列并将其安装在用户进程的堆栈中,以执行信号处理程序并发出中断-return 代码(这意味着一个特殊的机器执行信号处理程序的代码序列,然后将系统 returns 之前的 cpu 状态完全恢复为用户进程在时钟节拍之前正在做的事情)以应对中断到来的情况在一些合理的任务中间(异步中断可以在任何时间点,在任何用户代码机器指令之间)
最后,想象一个进程,由于系统负载已被换出到磁盘并且没有图像可用于 运行 代码(甚至信号处理程序代码已被换出)你如何执行如果没有数据结构或进程代码准备就绪,则信号处理程序 运行?
内核使用户代码执行信号处理程序的方式是调整进程堆栈以强制(在 return 从 syscal/interrupt 上)调用信号处理程序,然后恢复完整的 cpu 状态(因为它是从硬件中断完成的)所以进程可以继续执行机器指令,就好像两者之间没有发生任何事情一样。这是在 完成 kernel-mode/user-mode 开关之后完成的,因此唯一可行的做法就是调整堆栈。 Linux,就像 BSD 或所有其他 unix 风格一样,将此代码安装在进程映像中,以便它在每个用户模式进程中可用。