Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
434 views
in Technique[技术] by (71.8m points)

c - UNIX nonblocking I/O: O_NONBLOCK vs. FIONBIO

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);

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.

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 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.

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...