In operating system design, file descriptors are resources that users may either read bytes from or write bytes to. These may include actual files.
By convention:
0
: standard input (read)1
: standard output (write)2
: standard error (write)
In UNIX systems
On UNIX and Linux systems, there are several syscalls and utilities we can use to interact with file descriptors.
ssize_t write(int fd, const void buf[.count], size_t count)
: writescount
bytes to a file descriptor.ssize_t read(int fd, void buf[.count], size_t count)
: readscount
bytes from a file descriptor. Blocking syscall. If the file descriptor cannot be read from, it’ll exit the program. Otherwise, it won’t properly exit.int dup(int oldfd)
: allocates a new file descriptor that refers to the same file descriptor asoldfd
. The new FD number is the lowest available number.int dup2(int oldfd, int newfd)
: atomically changes the FDnewfd
to point tooldfd
. This closesnewfd
, and allocates its same FD number to point tonewfd
. This is done atomically to prevent any race conditions associated with doing this process manually, i.e., callingclose()
, thendup()
.