简体   繁体   English

在Linux和Windows下实现信号?

[英]Implementation of Signals under Linux and Windows?

I am not new to the use of signals in programming. 我不喜欢在编程中使用信号 I mostly work in C/C++ and Python. 我主要使用C / C ++和Python。 But I am interested in knowing how signals are actually implemented in Linux (or Windows). 但我很想知道如何在Linux(或Windows)中实际实现信号。

Does the OS check after each CPU instruction in a signal descriptor table if there are any registered signals left to process? 如果有任何注册信号需要处理,操作系统是否在信号描述符表中的每条CPU指令后检查? Or is the process manager/scheduler responsible for this? 或者是流程经理/调度程序对此负责?

As signal are asynchronous, is it true that a CPU instruction interrupts before it complete? 由于信号是异步的,CPU指令在完成之前是否会中断?

The OS definitely does not process each and every instruction. 操作系统绝对不会处理每个指令。 No way. 没门。 Too slow. 太慢了。

When the CPU encounters a problem (like division by 0, access to a restricted resource or a memory location that's not backed up by physical memory), it generates a special kind of interrupt, called an exception (not to be confused with C++/Java/etc high level language exception abstract). 当CPU遇到问题(例如除以0,访问受限资源或未被物理内存备份的内存位置)时,会产生一种特殊的中断,称为异常(不要与C ++ / Java混淆) / etc高级语言异常摘要)。

The OS handles these exceptions. 操作系统处理这些异常。 If it's so desired and if it's possible, it can reflect an exception back into the process from which it originated. 如果它是如此需要并且如果可能的话,它可以将异常反映回它发起的过程。 The so-called Structured Exception Handling (SEH) in Windows is this kind of reflection. Windows中的所谓结构化异常处理 (SEH)就是这种反思。 C signals should be implemented using the same mechanism. 应使用相同的机制实现C信号。

On the systems I'm familiar with (although I can't see why it should be much different elsewhere), signal delivery is done when the process returns from the kernel to user mode. 在我熟悉的系统上(虽然我不明白为什么它在其他地方应该有很大不同),但是当进程从内核返回到用户模式时,信号传递就完成了。

Let's consider the one cpu case first. 我们先考虑一个cpu案例。 There are three sources of signals: 有三种信号来源:

  • the process sends a signal to itself 该过程向自己发送信号
  • another process sends the signal 另一个进程发送信号
  • an interrupt handler (network, disk, usb, etc) causes a signal to be sent 中断处理程序(网络,磁盘,USB等)导致发送信号

In all those cases the target process is not running in userland, but in kernel mode. 在所有这些情况下,目标进程不在用户空间中运行,而是在内核模式下运行。 Either through a system call, or through a context switch (since the other process couldn't send a signal unless our target process isn't running), or through an interrupt handler. 通过系统调用,或通过上下文切换(因为除非我们的目标进程没有运行,其他进程无法发送信号),或通过中断处理程序。 So signal delivery is a simple matter of checking if there are any signals to be delivered just before returning to userland from kernel mode. 因此,信号传递是一个简单的问题,即在从内核模式返回用户空间之前检查是否有任何信号要传递。

In the multi cpu case if the target process is running on another cpu it's just a matter of sending an interrupt to the cpu it's running on. 在多CP​​U情况下,如果目标进程在另一个cpu上运行,那只需要向正在运行的cpu发送一个中断。 The interrupt does nothing other than force the other cpu to go into kernel mode and back so that signal processing can be done on the way back. 中断只会强制其他cpu进入内核模式并返回,以便在返回途中完成信号处理。

A process can send signal to another process. 进程可以将信号发送到另一个进程。 process can register its own signal handler to handle the signal. 进程可以注册自己的信号处理程序来处理信号。 SIGKILL and SIGSTOP are two signals which can not be captured. SIGKILL和SIGSTOP是两个无法捕获的信号。

When process executes signal handler, it blocks the same signal, That means, when signal handler is in execution, if another same signal arrives, it will not invoke the signal handler [ called blocking the signal], but it makes the note that the signal has arrived [ ie: pending signal]. 当进程执行信号处理程序时,它会阻塞相同的信号,这意味着,当信号处理程序执行时,如果另一个相同的信号到达,它将不会调用信号处理程序[称为阻塞信号],但它会记录信号到了[即:待定信号]。 once the already running signal handler is executed, then the pending signal is handled. 一旦执行了已经运行的信号处理程序,就处理待处理的信号。 If you do not want to run the pending signal, then you can IGNORE the signal. 如果您不想运行待处理信号,则可以忽略该信号。

The problem in the above concept is: 上述概念中的问题是:

Assume the following: process A has registered signal handler for SIGUSR1. 假设如下:进程A已为SIGUSR1注册了信号处理程序。

  1) process A gets signal SIGUSR1, and executes signalhandler()
  2) process A gets SIGUSR1,
  3) process A gets SIGUSR1,
  4) process A gets SIGUSR1,

When step (2) occurs, is it made as 'pending signal'. 当步骤(2)发生时,它是否为“未决信号”。 Ie; 即; it needs to be served. 它需要服务。 And when the step (3) occors, it is just ignored as, there is only one bit available to indicate the pending signal for each available signals. 并且当步骤(3)发生时,它被忽略,因为只有一个比特可用于指示每个可用信号的待决信号。

To avoid such problem, ie: if we dont want to loose the signals, then we can use real time signals. 为了避免这样的问题,即:如果我们不想丢失信号,那么我们就可以使用实时信号。

2) Signals are executed synchronously, 2)信号同步执行,

Eg., 例如。,

     1) process is executing in the middle of signal handler for SIGUSR1,

     2) Now, it gets another signal SIGUSR2, 

     3) It stops the SIGUSR1, and continues with SIGUSR2, 
        and once it is done with SIGUSR2, then it continues with SIGUSR1. 

3) IMHO, what i remember about checking if there are any signal has arrived to the process is: 3)恕我直言,我记得检查是否有任何信号到达该过程是:

1) When context switch happens.

Hope this helps to some extend. 希望这有一定的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM