我对在编程中使用信号并不陌生。我主要使用 C/C++ 和 Python 工作。但我很想知道信号是如何在 Linux(或 Windows)中实际实现的。
操作系统是否会在信号描述符表中的每条 CPU 指令之后检查是否有任何已注册的信号需要处理?还是流程经理/调度员对此负责?
由于信号是异步的,CPU指令在完成之前中断是真的吗?
我对在编程中使用信号并不陌生。我主要使用 C/C++ 和 Python 工作。但我很想知道信号是如何在 Linux(或 Windows)中实际实现的。
操作系统是否会在信号描述符表中的每条 CPU 指令之后检查是否有任何已注册的信号需要处理?还是流程经理/调度员对此负责?
由于信号是异步的,CPU指令在完成之前中断是真的吗?
操作系统绝对不会处理每条指令。没门。太慢了。
当 CPU 遇到问题(如除以 0、访问受限资源或没有物理内存支持的内存位置)时,它会生成一种特殊的中断,称为异常(不要与 C++/Java 混淆/etc 高级语言异常摘要)。
操作系统处理这些异常。如果它是如此需要并且如果可能的话,它可以将异常反映回它起源的过程中。Windows中所谓的结构化异常处理(SEH)就是这种反映。C 信号应该使用相同的机制来实现。
在我熟悉的系统上(尽管我看不出为什么它在其他地方会有很大不同),当进程从内核返回到用户模式时,信号传递就完成了。
让我们首先考虑一个 cpu 的情况。信号源有以下三种:
在所有这些情况下,目标进程都不是在用户态运行,而是在内核模式下运行。要么通过系统调用,要么通过上下文切换(因为除非我们的目标进程没有运行,否则其他进程无法发送信号),或者通过中断处理程序。因此,信号传递是一个简单的问题,即在从内核模式返回用户空间之前检查是否有任何信号要传递。
在多 cpu 的情况下,如果目标进程正在另一个 cpu 上运行,则只需向正在运行的 cpu 发送中断即可。中断除了强制另一个 cpu 进入内核模式并返回之外什么都不做,以便可以在返回的路上完成信号处理。
一个进程可以向另一个进程发送信号。进程可以注册自己的信号处理程序来处理信号。SIGKILL 和 SIGSTOP 是两个无法捕获的信号。
当进程执行信号处理程序时,它会阻塞相同的信号,也就是说,当信号处理程序正在执行时,如果另一个相同的信号到达,它不会调用信号处理程序[称为阻塞信号],但它会注意该信号已经到达[即:待处理信号]。一旦执行了已经运行的信号处理程序,就会处理挂起的信号。如果您不想运行挂起的信号,则可以忽略该信号。
上述概念中的问题是:
假设如下:进程 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,
当步骤 (2) 发生时,是否将其设为“未决信号”。IE; 它需要服务。并且当步骤(3)发生时,它只是被忽略,因为对于每个可用信号,只有一个比特可用于指示待处理信号。
为了避免这样的问题,即:如果我们不想丢失信号,那么我们可以使用实时信号。
2) 信号同步执行,
例如。,
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)恕我直言,我记得检查是否有任何信号到达该过程是:
1) When context switch happens.
希望这在一定程度上有所帮助。