Search code examples
cposixflagsfile-descriptor

File Descriptor flags and functions


I would like to know what happens with the O_NONBLOCK flag when I use the given file_des in a function. Does it keep the set flag, or not?

If not, should I reset it inside function? Is there any other way?

main()
{
    int file_des;

    fcntl(file_des, F_SETFD, O_NONBLOCK);
    function(file_des);

}

function(int file_des)
{
    //do something with file_des
    //What happens with the O_NONBLOCK flag?
}

Solution

  • File descriptors are process-wide. When used in a function, or a thread, they always work the same way. That way is controlled by status flags. In Linux, there are five status flags:

    • O_APPEND: Causes all writes to occur at the end of the file, ignoring file position.

    • O_ASYNC: A signal is generated when read or write is possible; only available for terminals, pseudoterminals, sockets, pipes, and FIFOs. (I do seem to recall it is available also for some character devices, but I have not verified which ones, if any; the man pages do not say.)

    • O_DIRECT: Skip page cache for I/O. Complicated, with many constraints; do not use except in very limited special circumstances.

    • O_NOATIME: Do not update last access time.

    • O_NONBLOCK: Non-blocking I/O. Instead of waiting (blocking) when data is not immediately available, or cannot be immediately sent, return a short count. If nothing can be sent or received, read()/write() etc. return -1 with errno == EWOULDBLOCK.
      O_NONBLOCK has no effect on normal files or block devices.

    You modify these by setting the new set of status flags using fcntl(fd, F_SETFL, flags), with zero or more flags OR'ed together. (To disable all, use zero.)

    The fcntl(fd, F_SETFD, dflags) sets the set of file descriptor flags. Currently, there is only one such flag, O_CLOEXEC, which causes the descriptor to be automatically closed when an execve() or other exec family of functions succeeds (including popen() and all others that fork and execute a new process). O_CLOEXEC is normally used as a flag for the open() call, though, to avoid the race window against another thread doing a fork() in between.

    When you use open(filename, flags) or open(filename, flags, mode), the flags argument is a combination of access mode (O_RDONLY, O_WRONLY, or O_RDWR; exactly one must be used), file creation flags (including file descriptor flags), and file status flags, OR'ed together. (Except for O_ASYNC, which cannot be specified at open() time, and must be set afterwards using fcntl(fd, F_SETFL, flags | O_ASYNC).)