【问题标题】:is execution of signal handler un-preemptible in linux?信号处理程序的执行在linux中是不可抢占的吗?
【发布时间】:2011-09-01 23:33:18
【问题描述】:

我有一个进程pSIGALRM 的信号处理程序注册。设置了一个定时器来周期性地发送信号SIGALRM 来处理p。还有多个线程在进程p 中运行。信号处理程序在被触发和执行时是否不可抢占?或者说,是不是signal handler的执行不会被进程中的任何线程中断p

PS:我认为信号处理程序是在内核中执行的(是吗?)并且内核对用户模式线程是不可抢占的?有不对的地方请指正...

【问题讨论】:

  • 它可以被抢占——信号处理程序代码没有什么特别之处。
  • 内核是抢占式的。它总是有事可做。

标签: multithreading operating-system signal-handling


【解决方案1】:

几乎 - 不要 - 在信号处理程序中处理共享数据几乎总是会导致痛苦的世界,同时处理线程也会让自己一团糟。

默认情况下,信号处理程序在运行时会被阻塞(至少在 linux 上,这可能不是普遍适用的),因此至少信号处理程序不会被自己抢占。但是,如果您有多个线程,并且信号没有在其他线程中被阻塞,则信号处理程序很可能会在多个线程中同时运行。

一个线程将接收信号并执行处理程序,哪个线程或多或少是随机的,尽管您可以通过在您不想处理信号的所有线程中阻塞信号来控制它。

但是,除处理信号的线程之外的任何其他线程都可能并行运行。处理信号的线程几乎可以在程序中的任何点运行信号处理程序(只要信号没有被阻塞)。因此,您需要某种锁定来保护该数据。问题是您不能使用任何正常的线程锁定原语,它们不是信号异步安全的。意思是如果你例如尝试在信号处理程序中获取 pthread_mutex_t,您很容易使程序死锁。

您可以在信号处理程序中安全调用的唯一函数是 here 列出的函数。 关于保护共享数据,您可以使用 sigblock()/sigunblock() 作为一种保护,确保在您访问共享数据时信号处理程序不会运行 - 并且信号必须在所有线程,否则它只会在没有被阻塞的线程之一中运行 - 沿着这条路走下去是疯狂的。

您可以在信号处理程序中安全访问的唯一共享数据几乎是 sig_atomic_t 类型,实际上其他类型的原始类型通常也是安全的。

你真正应该在信号处理程序中做的只是

  • 设置全局标志
  • 在合适的时候检查代码中其他地方的标志,然后采取行动

或者

  • 有某种主循环,使用 select()/poll() 或类似方法监视文件描述符中的事件。
  • 在主循环中创建一个管道并监控它
  • 将一个字节写入信号处理程序中的管道
  • 运行您的代码来处理信号,包括在主循环检测到该管道上的事件时保护任何共享数据

或者

  • 保留一个备用线程
  • 在所有线程中阻止给定信号
  • 在调用 sigsuspend() 时使用备用线程循环,并使用信号掩码确保该信号的传递。
  • 运行您的代码,包括保护任何共享数据以在 sigsuspend() 返回时处理信号

【讨论】:

  • 很好的解释!您已经涵盖了使用信号和多线程应用程序的大部分缺陷以及可能的解决方案!感谢您的详细解释。
【解决方案2】:

是信号处理程序,当被 触发并执行, 不可抢占?

不,信号处理程序像任何其他用户级函数一样是抢占式的。

我认为信号处理程序已执行 在内核中(是吗?)

不,信号处理程序不在内核模式下执行。

从内核模式切换到用户模式时,内核会检查进程的挂起信号。如果它找到一个挂起的信号,它会设置用户的堆栈帧,以便在返回用户模式后,进程开始执行信号处理程序。此后进程开始在用户模式下执行信号处理程序,就像任何其他用户级函数一样。执行完成后,进程切换到内核模式。然后内核恢复进程的原始上下文,在信号处理之前执行。
所有这些模式切换并不神奇。内核在用户栈中改变相应的返回地址。

【讨论】:

    【解决方案3】:

    简短的回答是“不”。

    阅读sigaction,尤其是 sa_mask 字段。默认情况下,即使在信号处理程序中,您的线程也可以被另一个信号中断。

    此外,短语“被进程 p 中的任何线程中断”是没有意义的。一般来说,线程是并发运行的;它们不会互相“打断”(调用 pthread_kill() 除外)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-22
      • 2014-06-11
      • 1970-01-01
      相关资源
      最近更新 更多