根据其手册页,select(( 系统调用提供了对一个或多个文件描述符的三个不同方面的监视:它们是否准备好读取、准备写入,或者是否发生了"错误"或"异常情况"(语言变化(。其中哪一个应该被监视,通过三个fd_set
参数指定,称为readfds
、writefds
和errorfds
。虽然有很多关于正确使用readfds
和writefds
的良好文档和示例,但我几乎找不到任何有用的errorfds
。
无论如何,出于下面讨论的原因,我尝试了errorfds
的使用,并且确实发现了一些情况,其中我的 runloop 中的 select()
调用响应其文件描述符之一的"异常条件"。例如,连接到 PTY 的 TTY,而后者从其主侧关闭,会引发这样的条件。
但是现在呢?我知道文件描述符上发生了一些"异常情况",但一般来说,我如何才能找出究竟是什么导致了它?只看errno
肯定不会给出答案(此时它总是 0(。也许有一些"神奇"的ioctl
是我应该注意的吗?
一些进一步的背景:我的许多程序(大部分是用C编写的(通过串行端口与外部硬件通信。为了进行测试,我还编写了一个简单的服务器,用于创建一个PTY,我的其他程序可以连接到该PTY,就好像它是串行端口一样。虽然在基本层面上所有这些都运行良好,但目前根本没有真正实现错误或其他异常情况的处理,这偶尔会导致非常讨厌的行为。这需要改变!
我特别感兴趣的一个特殊情况是连接是否已断开。例如,最好注意端口何时消失,例如,因为用户拉了USB到串行适配器。正确处理读写错误似乎可以避免最恶劣的意外副作用,但我想知道我是否应该做更多(观察errorfds
,或者其他一些信号(。不幸的是,UNIX信号处理是我根本不熟悉的东西。
我知道文件描述符上发生了一些"异常情况",但一般来说,我如何才能找出究竟是什么导致了它?也许有一些"神奇"的ioctl是我应该注意的吗?
您应该尝试读取 0 字节。至少在 Linux 中,man 2 read
指出:
如果计数为零,read(( 可能会检测到下面描述的错误。
因此,read(fd, NULL,0)
之后,您应该有一份告诉您更多内容的errno
,而无需实际阅读任何内容。手册页中的鼬鼠词可能意味着这可能不是很便携(cf read(fd, NULL, 0(;它有什么作用?它的定义是否明确?(