*nix中select和exceptfds/errorfds的语义

47

select系统调用需要3个文件描述符集,用于监视文件描述符的可读/可写和“异常”。

我的man page关于exceptfd描述符集并没有说明很多。它的作用是什么?文件描述符上可能会通知哪些类型的异常?

我假设这可能因描述符类型而异......无论是TCP套接字、管道、tty等)。是否有人有关于select在不同类型描述符上报告哪种错误的更多信息?

2个回答

36
有时人们认为需要使用exceptfds来检测错误,但这是一个误解。错误将在readfds中标记。尽管POSIX需要它(甚至将参数称为errorfds),但是否还在exceptfds中标记错误取决于操作系统。实际上,只有在关注异常情况时才需要此参数,但很少有必要检测这些条件。
什么被视为异常条件取决于文件描述符的类型,但迄今为止最常见的用法是在TCP套接字上,其中它表示可以使用带MSG_OOB标志的recv()读取带外数据。然而,TCP带外数据具有许多怪异之处(例如,仅1个字节可能会超时),因此很少使用。
在最近的Linux内核中,exceptfds可用于检测某些sysfs属性更改的情况。可以通过读取/sys下的相应文件来读取属性的当前值,对文件描述符进行select(),当属性更改时,exceptfds将被标记。然而,目前这仅适用于某些属性以及挂载更改(/proc/mounts)。
此外,某些设备驱动程序将使用exceptfds标记特定的设备特定条件。

1

你说得对,这取决于你使用文件描述符引用的设备类型。因此,对于套接字、FIFO、串口等设备,情况是不同的...

查看read()的man页面。在底部(至少在OS X中),它列出了您可以针对不同设备获得的不同错误。write()也是如此。

对于套接字、FIFO和其他IPC机制,我建议查看Unix网络编程第1卷和第2卷。如果我没记错的话,它描述了不同错误条件下可以预期的errnos。

我曾经使用FIFO走过这条路。最终我想到了生产者和消费者可以与FIFO的每一端交互的所有方式,然后为每种情况编写了测试用例。虽然有点繁琐,但这是发现所有不同错误条件的好方法。我学到了很多东西,最终代码也能正常工作了。


4
虽然很有趣,但那并没有回答问题。如果我理解你的回答正确,你在谈论可能在读取时触发的错误条件(errno),这与exceptfds无关。 - kriss
这是七年前的事了。我希望我能告诉你我当时是在提到什么,但是我甚至不记得写这个答案了。抱歉,我不能为你澄清我的陈述。 - Rob Jones

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接