【问题标题】:Updating global variable in signal handlers更新信号处理程序中的全局变量
【发布时间】:2013-08-16 10:24:49
【问题描述】:

除非像sig_atomic_t 这样的原子类型,否则全局变量不会在信号处理程序中更新。鉴于以下 2 个条件,我可以在信号处理程序中安全地编辑全局变量吗?

  1. 如果我只定义一个信号处理程序
  2. 如果我使用 sa_maskstruct sigaction 来阻止处理程序的所有信号
  3. 应用程序是单线程的

添加更多细节: 我有一个小的全局链表,其中保留了其子进程的一些信息。一旦我捕捉到 SIGCHLD (在父进程中),我想在我的信号处理程序中从链接列表中删除该节点。 我可以在具有上述条件并使用某种 pthread_mutex_trylock() 的信号处理程序中执行此操作吗?

【问题讨论】:

  • 关于其他信号或任务抢占?
  • 两者。我相信任务抢占不会发生,因为只有一个信号处理程序,并且在此处理程序完成之前,正常流程将不会恢复。请告知是否有其他任务抢占。
  • POSIX 信号没有排队,所以你不能假设你会可靠地为每个孩子获得一个单独的SIGCHLD。 (如果两个子进程大致同时退出,则只生成一个信号。)这意味着您应该在信号处理程序中获取 所有 待处理的子进程,或者更好的是,只需设置一个 @ 987654325@ 标记到您的主线程,或者将信号量提升到工作线程以进行实际的收割。

标签: c linux signals handler


【解决方案1】:

信号处理程序在访问静态数据结构时遇到问题。由此,您可以获得损坏的数据等。如果您尝试在信号处理程序中调用 printf(),很多时候您会得到奇怪的输出。

除非您使用原子类型,否则全局变量也是如此。

Signal handler won't see global variable

【讨论】:

  • 是的。刚刚记得信号可以是异步的,并且可以随时调用信号处理程序。可能是当进程在其正常流程中更新全局变量的中途时。在信号处理程序中更新或在正常流程恢复时,将导致损坏。
【解决方案2】:

sig_atomic_t 类型肯定会更新。您不能依赖任何其他类型在信号处理程序的上下文之外进行更新。它可能是,并且绝对不能保证它不会被更新。然而,这归结为缓存和多处理器的处理、异步执行和其他类似的事情。如果编译器认为一个变量不会改变,它可能会将它加载到一个寄存器中并且永远不会重新加载它。 sig_atomic_t 不允许这样做,所以它“不会出错”。

这类似于“在不同线程中更新全局变量”,更新需要在锁下或使用特殊的原子类型进行。您不能在信号处理程序中使用锁,因为当持有一些锁时可能会调用信号处理程序!

【讨论】:

  • 我的应用程序是单线程的。信号可以是异步的,并且可以随时调用信号处理程序。可能是当进程处于正常流程中更新全局变量的中间时。在信号处理程序中更新或在正常流程恢复时会导致损坏 我可以使用 pthread_mutex_trylock() 并安全地编辑全局变量吗? (如果进程在正常流程中获得锁,则使用 pthread_mutex_lock() 来避免死锁)
  • 您不能在信号处理程序中使用任何形式的锁定,因为在调用信号处理程序时不知道代码在哪里 - 它可能在设置一些 mutex (例如您尝试锁定的pthread_mutex)。您能否编辑您的问题以解释更多关于您实际尝试做什么、全局变量代表什么等?
猜你喜欢
  • 2013-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多