File Descriptors: Basics#

File Descriptors#

  • Universal handle for everything that’s got to do with I/O. You’d be surprised what fits under the “I/O” hat (signals, for example)

  • Not only files, but any kind of IO

    • Pipes

    • Sockets

    • FIFOs

    • Terminals

    • Device Special Files ⟶ entry points into kernel space

  • Type: int

../../../../../../../_images/file-descriptor.svg

Standard Filedescriptors#

  • File descriptors 0, 1, 2 are pre-allocated

  • Refer to terminal (“console”)

Number

POSIX Macro

<stdio.h>

<iostream>

0

STDIN_FILENO

stdin

std::cin

1

STDOUT_FILENO

stdout

std::cout

2

STDERR_FILENO

stderr

std::cerr

  • Interactive shell: all three associated with terminal

  • Standard input and output used for I/O redirection and pipes

  • Standard error receives errors, warnings, and debug output

File Descriptor Lifecycle - open/read/write/close#

  • Creation: depends on type of medium

    • open() for files and similar (roughly: what has a name in the filesystem)

    • socket() for networking endpoints

    • pipe() creates a pipe ⟶ two file descriptors

    • Many others with a more specialized background (e.g. signalfd, eventfd)

  • Usage

    • read() and write() for typical IO scenarios

    • ioctl() for non-IO operations

  • Cleanup: close() must be called on all file descriptors to free in-kernel memory

How Descriptor Numbers Are Chosen#

  • open() (and socket(), and …) have to choose a number

  • Which one is that? Random? ⟶ No!

../../../../../../../_images/first-free1.svg