我正在开发一个使用生产者和消费者线程的Linux应用程序。这是一个相当成熟的应用程序,我不想更改我的体系结构。
生产者和消费者线程通过可等待的队列链接。这是一个通过std :: queue与条件变量和互斥锁一起实现的类。
现在我希望消费者线程能够分叉/执行子进程,并等到子进程完成,或者等待队列非空,以先发生者为准。如果可等待队列非空,则必须终止子进程。 修改:子进程是无法更改的第三方应用。
一种可能性是当子进程终止时在我的条件变量上调用pthread_cond_signal(),但是如何实现呢?我不能使用SIGCHLD的处理程序,至少不能直接使用,因为man page表示不能从信号处理程序中使用pthread_cond_signal()。
一种可能的方法是生成子进程,然后启动一个线程到一个阻塞的waitpid(),最后是pthread_cond_signal()。这看起来有点笨拙:我真的需要生成一个线程只是为了关注pid吗?
对于混合waitpid和select / poll / epoll,有Self Pipe Trick。混合waitpid和条件变量是否有任何等价物?
注1:在某些实现中,SIGCHLD会中断条件变量等待函数。这是不可移植的,如果可能的话,我宁愿不依赖这种行为。
注2:由于条件变量封装在可等待的队列类中,我需要扩展此类以允许应用程序发出互斥锁信号。这只是一个简单的实现细节,我在我的问题中掩盖了这一点。
答案 0 :(得分:1)
也许这有效,但我不确定:
创建一个信号量,只要可等待队列本身要更改自己的锁定以指示状态更改,就会在可等待队列中注册并锁定/更改/解锁。你应该在拥有信号量时更改它自己的互斥锁。
为SIGCHLD
实现信号处理程序,然后在第三方应用程序终止时执行信号量锁定/更改/解锁,如果不是这样,则不执行任何操作。
在上面的例子中,他们将等待 1 并在你的信号量上增加(作为一个信号量操作),当他们想要获取信号量锁,然后完成他们的工作然后改变信号量到 0 (递减2),以便为等待的线程解锁它。这样你就不会有来自任何队列/第三方应用程序的两个成功锁。
在你的实际线程中,应该等待第三方应用程序终止或你的等待队列,你基本上等待锁定同一个信号量,同时等待 0 (并减少它,如果有其他服务员为0)。如果获取了锁,则检查可等待队列上的互斥锁是否已释放。如果没有,您知道您的第三方应用已终止。您执行工作,然后通过递增将信号量更改为 1 ,从而再次为您的队列和第三方应用解锁信号量。
由于semop(2)
- 锁定调用可以由信号处理程序中断,因此您必须检查EINTR
并循环任何锁定尝试。
如果保证信号处理程序将完成它的执行(我认为它是),这可能有效。