微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

什么时候处理信号?

如何解决什么时候处理信号?

我读过:

仅在接收过程返回时处理信号 从内核态到用户态。

但这对我来说没有意义,为什么

理论上,假设进程 A 正在运行并且它向进程 B 发送了一个信号,当进程 B 开始运行时,它可能永远不会在内核模式下运行,那些永远不会看到信号并对其进行处理的人。

但是,在现实世界中,信号几乎是立即处理的(至少从我自己的观察来看),这怎么可能,因为我看到了明显的矛盾?

解决方法

理论上,假设进程 A 正在运行并且它向进程 B 发送了一个信号,当进程 B 开始运行时,它可能永远不会在内核模式下运行,那些永远不会看到信号并对其进行处理的人。

Linux 是一个 preemptive multitasking 操作系统。这意味着内核给每个进程一个 time slice 并且 CPU 将在固定的时间间隔收到一个硬件 interrupt,这将返回到内核模式,这样内核就可以,例如,给不同进程的时间片。

因此,您描述的情况(进程将永远在用户模式下运行,永远不会到达内核模式)在 Linux 等抢占式多任务操作系统中永远不会发生。

,

但这对我来说没有意义,为什么?

信号必须在用户模式和发出信号的进程的进程上下文中处理,因此在进程发出系统调用(或执行另一个进程的线程)时无法处理它们。此外,由于这些系统调用中的许多具有原子性,因此只有机会中断系统调用来处理信号,或者在系统调用完成后处理它们。您只需要保证信号处理程序将任何其他进程的用户代码之前执行,但它们不是即时的(好吧,它们是,但仅从进程的角度来看,而不是从系统)

但最重要的原因是第一个:从内核模式返回接口具有特殊的代码来在从系统调用返回之前执行与信号关联的信号处理程序,但因为这必须是在用户模式下执行时,没有其他有效的方法来切换上下文、执行用户代码并返回到正在执行的内核代码。这也可能引发一系列安全问题(一个进程迫使内核调度超过允许的进程,因为它附加了很多信号处理程序)这段代码必须区分执行的内核模式是否是同步调用(一些系统调用由进程执行)或某些异步事件(硬件中断),因为用户代码必须模拟系统调用的返回(具有返回值和/或 errno 设置)或中断的返回(必须保留中断之前的所有寄存器和标志)此代码通常通过在切换到用户模式并返回之前调整用户堆栈(在内核模式下)来推送。

有一种特殊情况,其中进程被硬件中断(例如时钟滴答)中断,用户模式执行代码,并且检测到未决信号。然后,在返回用户代码之前,需要一个特殊的代码序列并安装在用户进程的堆栈中,以执行信号处理程序并发出中断返回代码(这意味着一个特殊的机器代码序列来执行信号处理程序,然后在系统返回到时钟滴答之前用户进程正在做的事情之前完全恢复 cpu 状态,以应对中断发生在一些合理的任务中间的情况(异步中断可以在任何时间点发生),在任何用户代码机器指令之间)

最后,想象一个进程,由于系统负载已被换出到磁盘,并且没有可用于运行代码的图像(甚至信号处理程序代码也已换出)如果没有数据结构,您如何执行信号处理程序或进程的代码是否准备好运行?

内核使用户代码执行信号处理程序的方式是调整进程堆栈以强制(从系统校准/中断返回时)调用信号处理程序,然后恢复完整的 CPU 状态(完成后)来自硬件中断),因此进程可以继续执行机器指令,就好像两者之间没有发生任何事情一样。这是在内核模式/用户模式切换完成后完成的,因此唯一可行的方法就是调整堆栈。 Linux,就像 BSD 或所有其他 unix 风格一样,在进程映像中安装此代码,以便它在每个用户模式进程中可用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。