我想同时等待一个文件描述符和一个互斥锁,推荐的方法是什么?

2024-05-08 23:34:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望派生出执行某些任务的线程,并使用线程安全队列与它们通信。我还想在等待的时候对各种文件描述符进行IO操作。

推荐的方法是什么?当队列从无元素变为某些元素时,我是否必须创建一个线程间管道并写入它?不是有更好的办法吗?

如果我必须创建线程间管道,为什么更多实现共享队列的库不允许您将共享队列和线程间管道创建为单个实体?

我想这样做的事实是否意味着一个根本的设计缺陷?

我问了关于C++和Python的问题。我对跨平台解决方案有点兴趣,但主要是对Linux感兴趣。

举个更具体的例子。。。

我有一些代码将在文件系统树中搜索内容。我有几个通过插座对外开放的通讯渠道。可能(或可能不会)导致需要在文件系统树中搜索内容的请求将到达。

我将在一个或多个线程中分离在文件系统树中搜索内容的代码。我想接受导致需要搜索树的请求,并将它们放入由搜索者线程执行的线程安全队列中。结果将被放入已完成搜索的队列中。

我希望能够在搜索过程中快速服务所有非搜索请求。我希望能够对搜索结果及时采取行动。

为传入请求提供服务通常意味着某种使用epoll的事件驱动体系结构。磁盘搜索请求队列和结果返回队列意味着一个线程安全队列,它使用互斥量或信号量来实现线程安全。

在空队列上等待的标准方法是使用条件变量。但如果我在等待时需要处理其他请求,那就不行了。要么我总是轮询结果队列(平均将结果延迟一半的轮询间隔),要么阻塞请求,要么不为请求提供服务。


Tags: 文件方法代码io实体元素内容管道
3条回答

我已经用您提到的pipe()和libevent(包装epoll)解决了这个问题。当工作线程的输出队列从空变为非空时,它会将一个字节写入其管道FD。这会唤醒主IO线程,然后主IO线程可以获取工作线程的输出。这很好的工作实际上是非常简单的代码。

你有Linux标签,所以我要抛出这个:POSIX Message Queues做所有这些,这应该满足你的“内置”请求,如果不是你不太想要的跨平台愿望。

线程安全同步是内置的。您可以在读取队列时阻止工作线程。或者,当队列中有新项时,MQs可以使用mq_notify()生成新线程(或发出现有线程的信号)。而且由于看起来您将使用select(),MQ的标识符(mqd_t)可以用作select的文件描述符。

无论何时使用事件驱动架构,都需要有一个单一的机制来报告事件完成情况。在Linux上,如果使用文件,则需要使用select或poll系列中的某些内容,这意味着必须使用管道来启动所有与文件无关的事件。

编辑:Linux有eventfdtimerfd。它们可以添加到您的epoll列表中,并用于分别从另一个线程或计时器事件触发时从epoll_wait中断。

还有另一个选择,那就是信号。可以使用fcntl修改文件描述符,以便在文件描述符变为活动时发出信号。然后,信号处理程序可以将文件就绪消息推送到您选择的任何类型的队列上。这可能是一个简单的信号量或mutex/condvar驱动的队列。由于现在不再使用select/poll,因此不再需要使用管道来对非基于文件的消息进行排队。

健康警告:我没有尝试过,虽然我看不出它为什么不能工作,但我并不真正知道signal方法的性能影响。

编辑:在信号处理程序中操作互斥锁可能是一个非常糟糕的主意。

相关问题 更多 >