sendto() 在 select() 上被阻塞

sendto() while blocked on select()

当主线程在 select() 上阻塞时,我可以从套接字上的其他线程调用 sendto() 以检查可读性吗?这种行为是否在 linux 或 windows 等不同系统中定义?或者我是否必须始终只从单个相同的线程做套接字相关的东西(select()/sendto()/recvfrom())?

我在我的应用程序中使用了这样的架构。我已经检查了多个来源(Linux)并且没有发现任何反对它的东西。

证明此概念的唯一正式基础是 POSIX 标准 - 它说 sendto() 以及 select() 是线程安全函数:

POSIX.1-2001 and POSIX.1-2008 require that all functions specified in the standard shall be thread-safe, except for the following functions

sendtoselect 未列出)来自 https://linux.die.net/man/7/pthreads.

所以如果函数是线程安全的,它的内部结构是安全锁定的,那么混合这两个函数应该也可以。但是我认为将 select()recvfrom() 混合使用是不正确的。也许它不会破坏程序,但唤醒两个等待线程会产生竞争条件。

关于 winsock,必须检查文档,它的实现如何遵循 POSIX 标准。我唯一发现的是 is winsock2 thread safe? , which partially anserwrs your question. In Linux you can examine it's opensource code: https://github.com/torvalds/linux/blob/master/net/socket.c https://github.com/torvalds/linux/blob/master/fs/select.c.

更新: 更有帮助 link https://groups.google.com/forum/#!topic/comp.os.linux.networking/cLbMGRNw8EA

从我的角度来看,从另一个线程调用 sendto 应该不会有任何问题。

"main thread is blocked on select()"

这仅意味着它是一个阻塞调用 - 它并不意味着它阻止其他人访问此资源(在本例中为套接字)。

可以,但它的设计看起来很奇怪。

  1. 可以。

    selectsendto都作用于套接字,套接字可以在线程甚至进程之间共享,前提是你同步它们,或者一个读一个写。如果您在 2 个线程上混合写入或读取,唯一的风险是仅获取部分数据(另一个线程获取另一部分)或产生垃圾,因为写入数据是混合的。如果一个线程使用 select 读取而另一个线程使用 writesendsendto 读取 writing 我看不出有任何问题

  2. 也许你不应该。

    线程和select是实现同一目标的两种方式:在同一进程中处理不同的通信通道。线程化时,通常的方法是在每个通道上分配一个线程,并让线程库或 OS 在每个线程有事要做时为每个线程分配处理器时间,就好像 所有线程同时执行。它会导致您一次编写一个任务的简单程序。

    select 系统调用被创建为具有一个中心点,该中心点被告知什么通信通道需要采取行动,然后明确地处理它。这样一来,您就有一个 waiting 点,预计会触发空头操作。您手动决定在什么时候应该做什么,并且可以确保除了 select 调用外永远不会被阻止。它导致非常高效的代码(无上下文更改开销),但代价是编写起来更复杂,因为您只编写小动作而不是整个任务。

    通常情况下,如果你继续select方式,你应该只使用线程进行长时间计算异步任务,而不是用于IO相关的任务。这就是为什么我认为你现在的设计很奇怪的原因。