我目前正在用 C++ 编写一个小型 shell。
作业和与之关联的 PID 存储在作业指针队列中 (job *)
。运行新作业时,有关它的信息将添加到队列中。由于可以同时处理多个作业,并且可以随时在 shell 的控制台输入新作业,因此我有一个信号处理程序来等待终止的作业。
当一个作业终止时,我需要从事件作业队列中删除它的信息并将其移动到我的已终止作业的双端队列中。但是,当另一个作业停止时,用户的新作业可能正在添加到队列中。
在这种情况下,他们的 insert
队列操作将被暂停,我的信号处理程序将被调用,它将执行它的 pop
操作。
我想了解如何解决这种潜在的竞争条件,因为我认为在此过程中可能会发生损坏。我不能使用互斥锁,因为如果被中断的父进程当时正在使用队列,就会发生死锁。
我看到一些关于 C++11
能够执行用户声明的原子操作的信息,以及关于 tasklet 的信息。不过,我不确定这些是否与我的问题相关。
有趣的是,我用作引用的示例 shell (MSH - http://code.google.com/p/mini-shell-msh/) 似乎没有对此类情况进行任何处理。信号处理程序会立即修改作业列表以及主控制台。也许我在这里忽略了什么?
一如既往,所有的反馈都是有用的。
最佳答案
您有多种方法可以避免竞争条件。
- 为作业指针使用无等待(原子)队列;
- 使用任何其他类型的队列,但使用
sigprocmask
(在非处理程序代码中)和sigaction中的适当
调用;sa_mask
值来保护它 - 根本不使用信号处理程序,使用一些允许以同步方式处理信号的不可移植系统调用:在 Linux 中可以使用
signalfd
,但不确定其他平台。
关于c++ - 访问队列数据结构的信号处理程序(竞争条件?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8146108/