我正在写一个小型服务器,它将接收来自多个来源的数据并处理这些数据。收到的来源和数据很重要,但不超过epoll应该能够很好地处理。但是,所有接收到的数据都必须解析并通过大量测试来运行,这些测试非常耗时,并且尽管epoll复用也会阻塞单个线程。基本上,该模式应该如下所示:IO-loop接收数据并将其捆绑到作业中,发送到池中可用的第一个线程,捆绑由作业处理,结果传递给IO循环写入文件。带C工作线程的epoll IO
我决定去找单个IO线程和N个工作线程。在IO线程接受的TCP连接,并读取数据是很容易使用,在提供的示例来实现: http://linux.die.net/man/7/epoll
线程通常也很容易对付,但我奋斗到epoll的IO循环与线程池结合一个优雅的方式。我无法找到在线工作人员在线使用epoll的“最佳做法”,但关于同一主题的问题很多。
因此,我有一些问题,我希望有人能帮助我回答:
- 可以(也应该)eventfd被用作IO线程和所有的工人之间的2路同步的机制?例如,每个工作线程有一个好主意,让它自己的epoll例程在一个共享的eventfd上等待(带有一个结构指针,包含关于该工作的数据/信息),即以某种方式使用eventfd作为工作队列?也可能有另一个eventfd将结果从多个工作线程传递回IO线程?
- 在IO线程发出有关套接字上更多数据的信号后,实际的recv是否应该在IO线程上发生,或者工作人员是否应该自己收回数据以便在解析数据帧时不阻塞IO线程等。?在那种情况下,我该如何确保安全,例如如果recv在工作线程中读取1,5帧数据并且另一个工作线程从相同连接接收到最后的0,5帧数据?
- 如果工作线程池是通过互斥锁等实现的,如果N + 1线程试图使用相同的锁,将等待锁定锁定IO线程吗?
- 是否有任何良好的实践模式,如何建立一个围绕epoll工作线程池与双向通信(即从IO到工人和后面)?
编辑:可以一个可能的解决方案是从IO循环更新环形缓冲区,更新后通过共享管道发送环形缓冲区索引给工作人员(因此放弃了该索引的控制权第一个从管道读取索引的工作者),让工作人员拥有该索引直到处理结束,然后再次通过管道将索引号发送回IO线程,从而给出控制权?
我的应用程序仅限于Linux,所以我可以使用Linux专用功能以尽可能最优雅的方式实现此功能。不需要跨平台支持,但性能和线程安全性是。
我想我可能有一个有用的解决方案,但需要知道,如何尽快拳头你知道单帧/包的长度吗?它们是固定长度的,是包含在数据包标题中还是只在最后才知道?如果你早点知道,在不占用主线程的情况下关闭工作要容易得多,但如果你不知道最后主线程不可避免地要做大量的读取。 – Vality
嗨,我知道recv后和迭代recv缓冲区后的长度。不幸的是,它们不是固定的长度,长度不会出现在数据包中,而是基于换行成帧。 – agnsaft