UNIX 非阻塞 I/O:O_NONBLOCK 与 FIONBIO [英] UNIX nonblocking I/O: O_NONBLOCK vs. FIONBIO

查看:94
本文介绍了UNIX 非阻塞 I/O:O_NONBLOCK 与 FIONBIO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我在 BSD 套接字编程上下文中遇到的每个示例和讨论中,将文件描述符设置为非阻塞 I/O 模式的推荐方法似乎是使用 O_NONBLOCK 标志为 fcntl(),例如

In every example and discussion I run across in the context of BSD socket programming, it seems that the recommended way to set a file descriptor to nonblocking I/O mode is using the O_NONBLOCK flag to fcntl(), e.g.

int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);

我已经在 UNIX 中进行网络编程十多年了,并且一直使用 FIONBIO ioctl() 调用来做到这一点:

I've been doing network programming in UNIX for over ten years, and have always used the FIONBIO ioctl() call to do this:

int opt = 1;
ioctl(fd, FIONBIO, &opt);

从来没有真正考虑过为什么.就是这么学的.

Never really gave much thought to why. Just learned it that way.

有人对其中一个或另一个可能各自的优点有任何评论吗?我想可移植性轨迹有所不同,但不知道在多大程度上 ioctl_list(2) 不涉及个别 ioctl 方法的这一方面.

Does anyone have any commentary on the possible respective merits of one or the other? I imagine the portability locus differs somewhat, but do not know to what extent as ioctl_list(2) doesn't speak to that aspect of individual ioctl methods.

推荐答案

在标准化之前有 ioctl(...FIONBIO...)fcntl(...O_NDELAY...),但它们在系统之间的行为不一致,甚至在同一系统内.例如,FIONBIO 在套接字上工作而 O_NDELAY 在 ttys 上工作是很常见的,在管道、fifos 和设备等方面存在很多不一致.如果您不知道自己拥有哪种类型的文件描述符,则必须同时设置两者才能确定.但除此之外,没有可用数据的非阻塞读取也不一致;取决于操作系统和文件描述符的类型,读取可能返回 0,或 -1 与 errno EAGAIN,或 -1 与 errno EWOULDBLOCK.即使在今天,在 Solaris 上设置 FIONBIOO_NDELAY 会导致读取没有数据在 tty 或管道上返回 0,或在套接字上返回 -1 和 errno EAGAIN.然而 0 是不明确的,因为它也为 EOF 返回.

Prior to standardization there was ioctl(...FIONBIO...) and fcntl(...O_NDELAY...), but these behaved inconsistently between systems, and even within the same system. For example, it was common for FIONBIO to work on sockets and O_NDELAY to work on ttys, with a lot of inconsistency for things like pipes, fifos, and devices. And if you didn't know what kind of file descriptor you had, you'd have to set both to be sure. But in addition, a non-blocking read with no data available was also indicated inconsistently; depending on the OS and the type of file descriptor the read may return 0, or -1 with errno EAGAIN, or -1 with errno EWOULDBLOCK. Even today, setting FIONBIO or O_NDELAY on Solaris causes a read with no data to return 0 on a tty or pipe, or -1 with errno EAGAIN on a socket. However 0 is ambiguous since it is also returned for EOF.

POSIX 通过引入 O_NONBLOCK 解决了这个问题,它具有跨不同系统和文件描述符类型的标准化行为.由于现有系统通常希望避免对可能破坏向后兼容性的行为进行任何更改,因此 POSIX 定义了一个新标志,而不是为其他系统之一强制执行特定行为.某些系统(如 Linux)对所有 3 个系统都一视同仁,并将 EAGAIN 和 EWOULDBLOCK 定义为相同的值,但希望保留一些其他遗留行为以实现向后兼容性的系统可以在使用旧机制时这样做.

POSIX addressed this with the introduction of O_NONBLOCK, which has standardized behavior across different systems and file descriptor types. Because existing systems usually want to avoid any changes to behavior which might break backward compatibility, POSIX defined a new flag rather than mandating specific behavior for one of the others. Some systems like Linux treat all 3 the same, and also define EAGAIN and EWOULDBLOCK to the same value, but systems wishing to maintain some other legacy behavior for backward compatibility can do so when the older mechanisms are used.

新程序应该使用 fcntl(...O_NONBLOCK...),按照 POSIX 的标准.

New programs should use fcntl(...O_NONBLOCK...), as standardized by POSIX.

这篇关于UNIX 非阻塞 I/O:O_NONBLOCK 与 FIONBIO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆