我正在开发一个使用生产者和消费者线程的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:由于条件变量封装在可等待的队列类中,我需要扩展此类以允许应用程序发出互斥锁信号.这只是一个简单的实现细节,我在我的问题中掩盖了这一点.
创建一个信号量,只要可等待队列本身要改变它自己的锁定以指示状态的改变,它就会在你的可等待队列中注册并被锁定/更改/解锁.您应该在拥有信号量时更改它自己的互斥锁.
为SIGCHLD实现信号处理程序,然后在第三方应用程序终止时执行信号量锁定/更改/解锁,如果不是这样,则不执行任何操作.
在上面的例子中,他们将等待1并在你的信号量上增加(作为一个信号量操作),当他们想要获取信号量锁,然后完成他们的工作然后将信号量更改为0(递减2)以便为你的等待线程解锁它.这样你就不会有来自任何队列/第三方应用程序的两个成功锁.
在你的实际线程中,应该等待第三方应用程序终止或你的等待队列,你基本上让它在等待0时等待锁定同一个信号量(如果还有其他服务员则减少它0).如果获取了锁,则检查可等待队列上的互斥锁是否已释放.如果没有,您知道您的第三方应用已终止.您执行工作,然后通过递增它将信号量更改为1,从而再次为您的队列和第三方应用程序解锁信号量.
由于semop(2)-lock调用可以由信号处理程序中断,因此您必须检查EINTR并循环任何锁定尝试.
如果保证信号处理程序将完成它的执行(我认为它是),这可能有效.