Ale*_*hov 90 c unix sockets network-programming
在我在BSD套接字编程的上下文中运行的每个示例和讨论中,似乎将文件描述符设置为非阻塞I/O模式的推荐方法是使用O_NONBLOCK
标志fcntl()
,例如
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
Run Code Online (Sandbox Code Playgroud)
我已经在UNIX中进行了十多年的网络编程,并且一直使用FIONBIO ioctl()
调用来执行此操作:
int opt = 1;
ioctl(fd, FIONBIO, &opt);
Run Code Online (Sandbox Code Playgroud)
从来没有真正考虑过为什么.刚学会这种方式.
有没有人对其中一个或两个可能各自的优点有任何评论?我认为可移植性轨迹在某种程度上有所不同,但不知道在多大程度上与ioctl_list(2)
单个ioctl
方法的那个方面没有对话.
mar*_*k4o 129
标准化此前有ioctl(
... FIONBIO
... )
和fcntl(
... O_NDELAY
... )
,但这些不一致表现系统之间,甚至在同一系统内.例如,通常FIONBIO
使用套接字并O_NDELAY
处理ttys,管道,fifos和设备等方面存在很多不一致之处.如果你不知道你有什么样的文件描述符,你必须设置两者以确定.但此外,没有数据的非阻塞读取也表明不一致; 取决于操作系统和文件描述符的类型,read可以返回0,或者使用errno EAGAIN返回-1,或者使用errno EWOULDBLOCK返回-1.即使在今天,设置FIONBIO
或O_NDELAY
在Solaris上导致没有数据的读取在tty或管道上返回0,或者在套接字上使用errno EAGAIN返回-1.但是0是不明确的,因为它也返回EOF.
POSIX通过引入解决了这个问题O_NONBLOCK
,它具有跨不同系统和文件描述符类型的标准化行为.由于现有系统通常希望避免对可能破坏向后兼容性的行为进行任何更改,因此POSIX定义了一个新标志,而不是强制要求其他任何一个行为的特定行为.像Linux这样的系统对所有3个系统都是相同的,并且还将EAGAIN和EWOULDBLOCK定义为相同的值,但是为了向后兼容而希望保留其他一些遗留行为的系统可以在使用旧机制时这样做.
新程序应使用fcntl(
... O_NONBLOCK
... )
,在POSIX标准.
正如@Sean所说,fcntl()
它基本上是标准化的,因此可以跨平台使用.该ioctl()
函数早fcntl()
于Unix,但根本没有标准化.那ioctl()
横跨相关的所有平台的工作给你,你是幸运的,但不能保证.特别是,用于第二个参数的名称是神秘的,并且跨平台不可靠.实际上,它们通常是文件描述符引用的特定设备驱动程序所独有的.(ioctl()
二十年前运行在运行PNX(Perq Unix)的ICL Perq上运行的位映射图形设备的调用从未转换为其他任何地方,例如.)