You guess wrong.
The only property which is per-file descriptor and which can be changed with
fcntl(F_SETFD) is the
FD_CLOEXEC close-on-exec flag.
All the other properties are either per file object ("open file description" in POSIX lingo -- which can be changed with
fcntl(F_SETFL)), or per inode.
Setting the non-blocking flag with
fcntl(F_SETFL, | O_NONBLOCK) or with
ioctl(FIONBIO) will affect all the file descriptors that refer to that open file. There is also no way to make a file non-blocking only for reading or writing.
This is far from ideal -- you can also refer to this Q&A on StackOverflow, especially the link to the lkml discussion about a failed attempt to fix it somehow.
Notice that regular files are basically non-blocking -- a
select(2) on them will return immediately.
If you're only interested in sockets, you should use
recv(2) with the
MSG_DONTWAIT flag instead of
write(2). Contrary to what you say, a socket file descriptor can be shared between processes no matter what its family/protocol/options are. And that also applies to a listening socket.