我有一个通过信号(特别是 SIGUSR1/SIGUSR2/SIGSTOP)与工作人员通信的应用程序。
我可以相信无论发生什么,每个信号都会由处理程序传递和处理吗?
如果信号的发送速度快于应用程序无法处理它们的速度(例如,由于此时主机负载很高),会发生什么情况?
除了“信号太多”的问题,信号可以被显式地忽略。来自man 2 signal
:
If the signal signum is delivered to the process, then one of the
following happens:
* If the disposition is set to SIG_IGN, then the signal is ignored.
Run Code Online (Sandbox Code Playgroud)
信号也可以被阻塞。来自man 7 signal
;
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
Run Code Online (Sandbox Code Playgroud)
阻塞和忽略的信号集都由子进程继承,因此应用程序的父进程可能会忽略或阻塞这些信号之一。
如果在进程处理完之前的信号之前传递了多个信号,会发生什么?这取决于操作系统。signal(2)
上面链接的联机帮助页讨论了它:
libc
,但我希望 BSD 行为。您不能相信发送的每个信号都会被传递。例如,如果进程需要很长时间来处理来自退出子进程的 SIGCHLD ,Linux 内核会“合并”SIGCHLD。
为了回答问题的另一部分,如果许多不同的信号在太短的时间间隔内到达,信号会在内核中“排队”。
您应该使用sigaction()
的sa_sigaction
成员来设置信号处理程序,仔细siginfo_t
设置参数的sa_mask
成员siginfo_t
。我认为这意味着至少要屏蔽所有“异步”信号。根据 Linux 的手册页sigaction()
,您还将屏蔽正在处理的信号。我认为您应该将sa_flags
成员设置为 SA_SIGINFO,但我不记得为什么我有这种迷信。我相信这将使您的进程成为一个信号处理程序,该处理程序在没有竞争条件的情况下保持设置状态,并且不会被大多数其他信号中断。
非常非常仔细地编写您的信号处理函数。基本上只需设置一个全局变量来指示信号被捕获,然后让进程的其余部分处理该信号所需的操作。信号将以这种方式被屏蔽的时间最短。
此外,您需要非常彻底地测试您的信号处理代码。把它放在一个小的测试过程中,尽可能多地发送 SIGUSR1 和 SIGUSR2 信号,可能来自 2 或 3 个专用信号发送程序。在您确信您的代码可以快速正确地处理 SIGUSR1 和 SIGUSR2 之后,还可以混合一些其他信号。为困难的调试做好准备。
如果您使用的是 linux 并且只使用 linux,您可能会考虑使用signalfd()
来创建一个文件描述符,您可以select()
或轮询来接收这些信号。使用signalfd()
可能会使调试更容易。
从某种意义上说,如果进程成功调用 kill
,那么目标将接收到信号。这是异步的:发送方无法知道信号何时被接收或处理。但是,这并不能保证信号会被传送。目标可能会在处理信号之前死亡。如果目标在传递信号时忽略了该信号,则该信号将无效。如果目标在处理之前收到多个相同信号编号的实例,则这些信号可能(通常是)合并:如果您向一个进程发送两次相同的信号,则无法知道该进程是否会收到该信号一次或两次。信号主要是为了杀死一个进程或作为一种让进程引起注意的方式,它们不是为通信而设计的。
如果您需要可靠的交付,那么您需要不同的通信机制。进程间主要有两种通信机制:管道允许单向通信;一个插座允许双向通信和到同一服务器的多个连接。如果您需要目标处理尽可能多的通知,请通过管道发送字节。
归档时间: |
|
查看次数: |
8953 次 |
最近记录: |