6

我正在开发一个使用生产者和消费者线程的 linux 应用程序。这是一个相当成熟的应用程序,我不想过多地改变架构。

生产者和消费者线程通过等待队列链接。这是一个通过 std::queue 以及条件变量和互斥锁实现的类。

现在我希望消费者线程能够派生/执行子进程,并等待子进程完成或等待队列非空,以先发生者为准。如果等待队列不为空,则必须终止子进程。编辑:子进程是无法更改的第三方应用程序。

一种可能性是当子进程终止时在我的条件变量上调用 pthread_cond_signal() ,但如何实现呢?我不能使用 SIGCHLD 的处理程序,至少不能直接使用,因为手册页说 pthread_cond_signal() 不能从信号处理程序中使用。

一种可能的方法是生成子进程,然后启动一个线程到阻塞的 waitpid(),最后是 pthread_cond_signal()。不过,这似乎有点笨拙:我真的需要生成一个线程来监视 pid 吗?

对于混合 waitpid 和 select/poll/epoll 有Self Pipe Trick。混合 waitpid 和条件变量是否有任何等价物?

注 1:在某些实现中,SIGCHLD 会中断条件变量等待函数。这不是可移植的,如果可能的话,我宁愿不依赖这种行为。

注意 2:由于条件变量封装在可等待队列类中,我需要扩展此类以允许应用程序向互斥体发出信号。这只是一个微不足道的实现细节,我在我的问题中已经掩饰了。

4

1 回答 1

1

也许这有效,但我不确定:

创建一个信号量,该信号量将在您的等待队列中注册,并在等待队列本身要更改其自己的锁以指示状态更改时锁定/更改/解锁。您应该在它持有信号量时更改它自己的互斥锁。

为 实现一个信号处理程序SIGCHLD,然后在第 3 方应用程序终止时执行信号量锁定/更改/解锁,如果不是这种情况,则不执行任何操作。

在上述情况下,他们将等待1并在您的信号量上递增(作为一个信号量操作),当他们想要获取信号量锁时,然后做他们的工作,然后将信号量更改为0(递减 2)以便为您的等待线程解锁它。这样,您将不会连续地从任何队列/第 3 方应用程序中获得两个成功的锁。

在您的实际线程中,应该等待第 3 方应用程序终止或您的可等待队列,您基本上让它在等待0时等待锁定同一信号量(如果有其他服务员,则将其递减) 0)。如果获得锁,则检查等待队列上的互斥锁是否已释放。如果没有,您就知道您的第 3 方应用程序已终止。您执行您的工作,然后将您的信号量更改为1,从而再次解锁队列和第 3 方应用程序的信号量。

由于semop(2)-lock 调用可能会被信号处理程序中断,因此您必须检查EINTR并循环您拥有的任何锁定尝试。

如果保证信号处理程序将完成它的执行(我认为它是),这可能会起作用。

于 2012-09-06T13:18:20.370 回答