在单线程程序中,信号处理程序中是否可能存在竞争条件?
void signal_handler(...)
{
static int i = 0;
i = i + 10 * 10;
}假设抛出了两个非常接近的信号,如此接近,以至于它们同时进入函数。
我找不到有关最新的Linux操作系统如何处理此问题的信息。我只知道这两个信号都被正确处理了,但我不知道如何处理。竞争条件是可能的吗?
感谢您的帮助,谢谢!
发布于 2013-05-30 04:43:04
在你所指的意义上(两个信号之间)没有竞争条件。同一信号的多个信号不会同时传送。除非采取预防措施,否则可能会同时传送不同信号号的多个信号,如torek的答案中所述。
当您涉及静态持续时间的变量(或全局变量)时,您的函数可能不再是可重入的。这通常对信号处理函数本身并不重要。但是,如果它调用访问全局或静态数据的其他函数,则该函数将看到类似于两个线程竞相通过临界区的访问模式。也就是说,您的程序正在调用这样一个函数来执行其正常处理,但是信号在该函数的中间到达,然后您的信号处理程序调用该函数。全局/静态变量可能处于不一致的状态,并可能导致您的程序具有不确定的行为。
POSIX定义了一组API,可以从信号处理程序中安全地调用这些API。当您计划让信号处理程序调用您实现的函数时,您的代码应该采取类似的预防措施。
发布于 2013-05-30 04:25:37
单线程意味着一次只有一个应用程序接触静电,对吗?如果有2个应用程序,则有2个静态,没有竞态条件。
如果这是一个中断处理程序,并且I CPU 100不是原子的(它可能取决于平台/ += ),那么它将竞争。
发布于 2013-05-30 06:33:10
考虑单进程P1的情况,它有一个与上面显示的信号处理程序类似的信号处理程序。假设您正在捕获信号SIGUSR1,并让它进入函数signal_handler。当您在signal_handler中时,其他进程P2会向P1发送另一个SIGUSR1 (例如,通过kill)。此信号通过sa_mask被“阻塞”(暂时),直到signal_handler在P1中返回。即使你没有在sa_mask中设置任何位(只要你没有在sa_flags中设置SA_NODEFER,见下文),这也是正确的。
但是,假设您还决定使用signal_handler函数来捕获SIGUSR2。假设P2也发送了一个SIGUSR2。在这种情况下,SIGUSR2被捕获(或可能被捕获),启动另一个正在运行的signal_handler实例,这次是代表SIGUSR2信号。
您可以通过确保在处理SIGUSR1时,SIGUSR2也被临时阻止来防止这种情况。通常,您可能希望在处理SIGUSR2时阻塞SIGUSR1。为此,在sa_mask中设置两个相应的位
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_flags = SA_RESTART | SA_SIGINFO; /* (decide for yourself which flags) */
sigaddset(&sa.sa_mask, SIGUSR1);
sigaddset(&sa.sa_mask, SIGUSR2);
sa.sa_sigaction = signal_handler;
error = sigaction(SIGUSR1, &sa, NULL);
if (error) ... handle error ...
error = sigaction(SIGUSR2, &sa, NULL);
if (error) ... handle error ...这两个sigaddset调用确保SIGUSR1和SIGUSR2在函数的持续时间内都被暂停(暂时阻塞)。
(请注意,操作系统在进入和退出信号处理程序时对信号的自动阻止和解除阻止是通过sigprocmask完成的,使用SIG_BLOCK和SIG_SETMASK-notSIG_UNBLOCK-with SIG_SETMASK at exit设置的掩码,通过保存通过SIG_BLOCK填充的前一个掩码。这通常是在内核代码中完成的,而不是实际调用sigprocmask,但效果是相同的,只是效率更高。)
https://stackoverflow.com/questions/16823102
复制相似问题