信号处理程序的执行在Linux中不可抢占吗?

问题描述

| 我有一个进程
p
注册了handler1ѭ的信号处理程序。设置了一个计时器,以定期发送信号
SIgalRM
来处理
p
。在进程ѭ0中还运行着多个线程。信号处理程序在被触发和执行时是否不可抢占?或者说,信号处理程序的执行是否不会被进程“ 0”中的任何线程中断? PS:我以为信号处理程序是在内核中执行的(是吗?),而内核对于用户模式线程是抢占式的?纠正我是否有错...     

解决方法

几乎-不-在信号处理程序中处理共享数据几乎总是会导致痛苦的世界,同时也要处理线程,这会使您陷入混乱。 默认情况下,信号处理程序在运行时会被阻止(至少在linux上,这可能并非普遍如此),因此至少信号处理程序本身不会被抢占。但是,如果您有多个线程,并且在其他线程中没有阻塞信号,则信号处理程序很可能在多个线程中同时运行。 一个线程将接收信号并执行处理程序,虽然可以通过在所有不想处理该信号的线程中阻塞信号来控制它,但它或多或少是哪个线程。 但是,其他任何线程都禁止处理信号的线程并行运行。处理信号的线程几乎可以在程序中的任何位置运行信号处理程序(只要信号未被阻塞即可。)因此,您需要某种锁定来保护该数据。问题是您不能使用任何普通的线程锁定原语,它们不是信号异步安全的。意思是如果你例如尝试在信号处理程序中获取pthread_mutex_t,很容易使程序死锁。 您可以在信号处理程序中安全调用的唯一函数是此处列出的函数。 关于保护共享数据,您可以使用sigblock()/ sigunblock()作为一种保护,以确保在访问共享数据时信号处理程序不会运行-并且信号必须在所有线程,否则它将只在没有阻塞的线程之一内运行-走那条路是疯狂的。 可以在信号处理程序中安全访问的唯一共享数据几乎是
sig_atomic_t
类型,实际上,其他类型的原始类型也通常是安全的。 您在信号处理程序中真正应该做的就是 设置全局标志 在适当的时候检查代码中其他位置的标志,并采取措施 要么 有某种主循环,它使用select()/ poll()或类似方法监视文件描述符中的事件。 创建一个管道并在主循环中对其进行监视 向信号处理程序中的管道写入一个字节() 运行您的代码以处理信号,包括在mainloop在管道上检测到事件时保护所有共享数据 要么 保留备用线程 阻塞所有线程中的给定信号 在使用信号掩码调用sigsuspend()时,要有备用线程循环,以确保传递该信号。 运行您的代码,包括保护所有共享数据以在sigsuspend()返回时处理信号     ,  是信号处理程序时   触发并执行,   不可抢占? 不,信号处理程序像其他任何用户级功能一样都是抢占式的。   我以为信号处理程序已执行   在内核中(是吗?) 不,信号处理程序不在内核模式下执行。 从内核模式切换到用户模式时,内核检查是否有待处理信号。如果找到待处理的信号,则会设置用户的堆栈帧,以便在返回用户模式后,该过程开始执行信号处理程序。此后,该过程开始在用户模式下执行并执行信号处理程序,就像其他任何用户级功能一样。执行完成后,进程将切换到内核模式。内核然后恢复处理的原始上下文,该过程在信号处理之前执行。 所有这些模式切换都不是魔术。内核在用户堆栈中更改适当的返回地址。     ,最简洁的答案是不\”。 阅读有关sigaction的内容,尤其是sa_mask字段。默认情况下,即使线程处于信号处理程序中,它也可以被另一个信号中断。 同样,短语“被进程p中的任何线程中断”也没有意义。通常,线程是并发运行的。它们不会彼此“中断”(通过调用pthread_kill()除外)。     

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...