在我在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...)fcntl(...O_NDELAY...),但它们在系统之间,甚至在同一系统内的行为都不一致.例如,FIONBIO处理套接字和O_NDELAY处理TTY是很常见的,在管道、FIFO和设备等方面存在很多不一致性.如果你不知道你有什么样的文件描述符,你就必须同时设置这两种描述符.但除此之外,无数据可用的非阻塞读取也被不一致地指示;根据操作系统和文件描述符的类型,读取可能返回0,或-1(带有errno EAGAIN)或-1(带有errno eWooldblock).即使在今天,在Solaris上设置FIONBIOO_NDELAY也会导致没有数据的读取在tty或管道上返回0,或者在套接字上返回带有errno EAGAIN的-1.但是,0是不明确的,因为它也是为EOF返回的.

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

新程序应该使用fcntl(...O_NONBLOCK...),由POSIX标准化.

C++相关问答推荐

如何在 C++ 中包含使用 C++ 关键字作为标识符的 C 标头?

删除逗号之间的白色字符,但不删除逗号内的内容

关于函数中返回局部指针变量的问题

C 是否有 [[nodiscard]] 机制在忽略值时发出警告?

为什么下面的循环展开会导致错误的结果?

C中指向结构的指针与指向数组的指针

将 char 转换为二进制字符串,反之亦然

如何解读一个单词并在 C 的 txt 文件中找到它的所有匹配项?

如何编写结构变量的读取函数?

如何让我的应用程序找到 gettext 翻译?

如何仅使用互斥锁来解决哲学家进餐问题?

C printf中的'I'(大写i)标志是什么?

我们可以在变量名中写注释吗?

为什么 rand() 在 Linux 上重复数字的频率远高于 Mac?

从函数返回结构时可能出现 GCC 错误

C 中数组索引的求值顺序(相对于表达式)

为什么 C++ 初始分配比 C 大得多?

程序是 32 位还是 64 位意味着什么?

为什么在启用 GCC 优化的情况下,这段代码使用 strlen 的速度要慢 6.5 倍?

在结构中,使用一个数组字段访问另一个数组字段是否合法?