6

我目前正在用 C++ 编写一个小 shell。

作业和与之关联的 PID 存储在作业指针队列中(job *)。运行新作业时,有关它的信息将添加到队列中。由于可以同时处理多个作业,并且可以随时在 shell 的控制台中输入新作业,因此我有一个信号处理程序来等待终止的作业。

当作业终止时,我需要从活动作业队列中删除它的信息并将其移动到我的已终止作业的双端队列中。但是,当另一个作业停止时,可能会将用户的新作业添加到队列中。

在这种情况下,他们的insert队列操作将被暂停,我的信号处理程序将被调用,它将执行它的pop操作。

我试图了解如何解决这种潜在的竞争条件,因为我认为在此过程中可能会发生损坏。我不能使用互斥锁,因为如果被中断的父进程当时正在使用队列,则会发生死锁。

我看到了一些关于C++11能够执行用户声明的原子操作的信息,以及有关 tasklet 的信息。我不确定这些是否与我的问题有关。

有趣的是,我用作参考的示例外壳(MSH - http://code.google.com/p/mini-shell-msh/)似乎没有对此类条件进行任何处理。信号处理程序与主控制台一起立即修改作业列表。也许我在这里忽略了什么?

与往常一样,所有反馈都会得到认可。

4

2 回答 2

4

您有几种方法可以避免竞争条件。

  • 对作业指针使用无等待(原子)队列;
  • 使用任何其他类型的队列,但使用sigprocmask(在非处理程序代码中)并sa_mask在调用中使用适当的值来保护它sigaction
  • 根本不使用信号处理程序,使用一些允许以同步方式处理信号的不可移植系统调用:在 Linux 中可以使用signalfd,但不确定其他平台。
于 2011-11-16T13:01:15.443 回答
1

您需要sigprocmask()在非处理程序代码中的关键部分周围禁用信号。这类似于内核中的设备驱动程序在更新与中断处理程序共享的结构时禁用驱动程序用户部分的中断。

于 2011-11-16T04:20:10.187 回答