Skip to content

fcntl()

Purpose

fcntl() performs file descriptor control operations.

In these labs, it is commonly used to:

  • Enable non-blocking I/O (O_NONBLOCK)
  • Configure asynchronous notification (F_SETOWN and O_ASYNC)
  • Set close-on-exec behavior (FD_CLOEXEC)
#include <fcntl.h>
#include <unistd.h>

Prototype

int fcntl(int fd, int cmd, ...);

Common Commands

Command Purpose
F_GETFL Get file status flags.
F_SETFL Set file status flags, such as O_NONBLOCK.
F_GETFD Get file descriptor flags.
F_SETFD Set file descriptor flags, such as FD_CLOEXEC.
F_SETOWN Set the process or process group that receives SIGIO.

Asynchronous Notification

Signal-driven I/O is enabled by combining F_SETOWN and O_ASYNC.

fcntl(fd, F_SETOWN, getpid());

int flags = fcntl(fd, F_GETFL);

fcntl(fd, F_SETFL, flags | O_ASYNC);

F_SETOWN specifies the process that receives SIGIO, while O_ASYNC enables asynchronous notification on the file descriptor.

Minimal Example

int flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
    return -1;

if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
    return -1;

Common Pitfalls

  • Overwriting existing flags instead of OR-ing with them.
  • Confusing file status flags (O_NONBLOCK) with descriptor flags (FD_CLOEXEC).
  • Forgetting that non-blocking behavior changes read() and write() error handling.
  • F_SETOWN alone does not enable asynchronous notification.
  • O_ASYNC requires driver support for .fasync().