在我在 BSD 套接字编程上下文中遇到的每个示例和讨论中,似乎将文件描述符设置为非阻塞 I/O 模式的推荐方法是使用 O_NONBLOCK
标志到 fcntl()
,例如
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
我已经在 UNIX 中进行网络编程十多年了,并且一直使用
FIONBIO ioctl()
调用来执行此操作:int opt = 1;
ioctl(fd, FIONBIO, &opt);
从来没有真正考虑过为什么。就是这么学的。
有没有人对一个或另一个可能各自的优点有任何评论?我想可移植性轨迹有所不同,但不知道在多大程度上
ioctl_list(2)
不涉及个别 ioctl
方法的这一方面。 最佳答案
在标准化之前有 ioctl(
... FIONBIO
... )
和 0x2518122231343141 ... 0x2518122315134 之间的系统相同,但在这些系统中的行为不一致 23, 13113134, 甚至 134, 134, 134, 134, 134例如,fcntl(
在套接字上工作很常见,O_NDELAY
在 tty 上工作是很常见的,在管道、FIFO 和设备等方面存在很多不一致。如果您不知道自己拥有哪种类型的文件描述符,则必须同时设置两者才能确定。但除此之外,没有可用数据的非阻塞读取也不一致;取决于操作系统和文件描述符的类型,读取可能返回 0,或 -1 与 errno EAGAIN,或 -1 与 errno EWOULDBLOCK。即使在今天,在 Solaris 上设置 )
或 FIONBIO
会导致在 tty 或管道上没有数据的读取返回 0,或者在套接字上返回 -1 和 errno EAGAIN。然而 0 是不明确的,因为它也为 EOF 返回。
POSIX 通过引入 O_NDELAY
解决了这个问题,它具有跨不同系统和文件描述符类型的标准化行为。由于现有系统通常希望避免对可能破坏向后兼容性的行为进行任何更改,因此 POSIX 定义了一个新标志,而不是为其他系统之一强制执行特定行为。某些系统(如 Linux)对所有 3 种处理方式相同,并且还将 EAGAIN 和 EWOULDBLOCK 定义为相同的值,但是当使用旧机制时,希望维护一些其他遗留行为以实现向后兼容性的系统可以这样做。
新程序应使用 FIONBIO
... O_NDELAY
... O_NONBLOCK
,如 POSIX 所标准化。
关于c - UNIX 非阻塞 I/O : O_NONBLOCK vs. FIONBIO,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1150635/