当前位置:  开发笔记 > 运维 > 正文

如何通知select()立即返回?

如何解决《如何通知select()立即返回?》经验,为你挑选了1个好方法。

我有一个工作线程正在侦听TCP套接字以获取传入流量,并缓冲接收到的主线程要访问的数据(让我们称之为套接字A).然而,工作线程也有做一些常规操作(比如,每秒一次),即使没有数据进来,所以我用select()了超时,让我不需要保持轮询.(请注意,调用receive()在非阻塞套接字,然后睡一秒钟也不好:输入数据应该是立即可用于主线程,即使主线程可能并不总是能够处理它的时候了,因此需要缓冲.)

现在,我还需要能够发信号通知工作线程立即做其他事情; 从主线程,我需要立即让工作线程select()返回.现在,我已经解决了这个问题(方法基本上从这里和这里采用):

在程序启动时,工作线程用于此目的创建数据报(UDP)类型的附加插座,并将其绑定到一些随机端口(我们称之为插座).同样,主线程创建一个用于发送的数据报套接字.在其号召select(),工作线程,将列出一个fd_set.当主线程需要发信号时,它sendto()是相应端口的几个字节localhost.回到工作线程中,如果B保留在fd_setafter select()返回中,则recvfrom()调用并且接收的字节被简单地忽略.

这似乎工作得很好,但我不能说我喜欢这个解决方案,主要是因为它需要为B绑定一个额外的端口,还因为它添加了几个额外的套接字API调用,这可能会失败我猜 - 我不知道真的想要找出每个案件的适当行动.

我认为理想情况下,我想调用一些以A作为输入的函数,除了立即select()返回之外什么都不做.但是,我不知道这样的功能.(我想我可以举例来说shutdown()套接字,但副作用并不是真的可以接受:)

如果这是不可能的,那么第二个最佳选择是创建一个比真正的UDP套接字更糟糕的B,并且实际上并不需要分配任何有限的资源(超出合理的内存量).我想Unix域套接字就可以做到这一点,但是:解决方案不应该比现在的解决方案少得多,尽管一些适量的#ifdef东西都可以.(我主要针对Windows和Linux - 并且顺便编写C++.)

请不要建议重构以摆脱两个单独的线程.这种设计是必要的,因为主线程可能会被长时间阻塞(例如,做一些密集的计算 - 我无法receive()从最里面的计算循环开始定期调用),同时,有人需要缓冲传入的数据(由于我无法控制的原因,它不能是发件人).

现在我正在写这篇文章,我意识到有人肯定会简单地回复" Boost.Asio ",所以我刚刚看了它......但是找不到明显的解决方案.请注意,我也不能(轻松地)影响套接字A的创建方式,但如果需要,我应该可以让其他对象包装它.



1> Alex B..:

你快到了.使用"自我管道"技巧.打开一个管道,将其添加到您的select()读取和写入fd_set,从主线程写入它以取消阻止工作线程.它可以跨POSIX系统移植.

我在一个系统中看到了Windows的类似技术的变体(实际上与上面的方法一起使用,分开#ifdef WIN32).可以通过向其添加虚拟(未绑定)数据报套接字fd_set然后将其关闭来实现解除阻塞.缺点是,当然,你必须每次都重新打开它.

然而,在前述系统中,这两种方法都被相当谨慎地使用,并且用于意外事件(例如,信号,终止请求).首选方法仍然是变量超时select(),具体取决于为工作线程调度的时间.

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有