【问题标题】:Unix: What happens when a read file descriptor closes while calling select()Unix:当读取文件描述符在调用 select() 时关闭时会发生什么
【发布时间】:2012-04-06 16:20:09
【问题描述】:

假设我在包含一堆读取文件描述符的 FD_SET 上调用 select()。如果在 select() 调用期间,文件描述符之一关闭,会发生什么情况?假设发生了某种错误,那么我是否有责任从集合中查找并删除已关闭的文件描述符?

【问题讨论】:

  • 请记住,当您在 select() 调用中时,驻留在 fd_set 中的文件描述符唯一可能的方法是如果另一个线程关闭()该描述符。 (让对等方或本地 tcp/ip 堆栈关闭 tcp 连接是另一回事)。

标签: c unix


【解决方案1】:

我不相信这是在任何地方指定的;一些系统可能会立即从select 返回,而其他系统可能会继续阻塞。请注意,发生这种情况的唯一方法是在多线程进程中(否则,close 不会在 select 期间发生;即使它发生在信号处理程序中,select 也会被信号中断) .因此,出现这种情况可能表明您有更大的问题需要担心。如果您正在轮询的文件描述符之一可以在select 期间关闭,更大的问题是同一文件描述符可能会在close 之后立即重新分配给新打开的文件(例如,在另一个不相关的线程中打开的文件) ,然后轮询的线程可能会错误地对“属于”不同线程的新文件执行 IO。

如果您的数据对象由一组文件描述符组成,在多线程程序中将使用select 进行轮询,那么您几乎肯定需要使用某种同步原语来控制对该集合的访问,并且添加或删除文件描述符应该需要一个互斥锁,select(或成员上的任何 IO)可能正在进行中。

当然在多线程程序中,最好不要使用select,而是让多线程中的阻塞IO达到预期的效果,而不需要复杂的锁定逻辑。

【讨论】:

    【解决方案2】:

    select() 系统调用采用三个fd_set 参数:Send、Receive、Exception。要检查,如果读取文件描述符上发生错误,请将其包含在读取(接收)和错误(异常)集中 - 在从select() 返回的异常集中看到它意味着,该套接字上发生了异常,让您有机会了解什么。

    一般来说,出现任何异常的网络套接字将不再适合发送和接收。

    【讨论】:

    • 其实exceptfds是用于紧急数据的。
    • linux.die.net/man/2/select 以及我的经验另有说明:“将监视 exceptfds 中的那些 [文件描述符] 以查找异常”
    • 我不喜欢宣传我的答案,但我确实添加了链接和引用。
    【解决方案3】:

    即使您已经读取了所有发送的数据,关闭的套接字也始终被视为准备好读取。 Select 将解除阻塞,表示该套接字可用。

    【讨论】:

      猜你喜欢
      • 2014-12-20
      • 2012-11-18
      • 2021-05-08
      • 2019-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-09
      相关资源
      最近更新 更多