The Linux filesystem describes how files are stored and maintained on Linux systems. As with many constructs in Linux, the filesystem follows POSIX specifications, so they share similar structure as BSD, Unix, and macOS.

Structure

As with many filesystems, POSIX filesystems are stored as a directed acrylic graph (basically a tree). There are some important directories:

  • /: is the root directory. It functions as the parent directory for all other directories and files in the system.
  • ~: user home directory.
  • .: current directory.
  • ..: parent directory.
  • mnt: where mounted devices or filesystems (like USBs) are maintained.

We always work within a working directory. Then, relative paths are described relative to the current working directory. Absolute paths are the full paths starting from the root directory.

Common commands

  • pwd: prints the current working directory.
  • cd: changes the current directory. We use .. to get to the parent level, and a specific folder name to get to a child level. For directories with spaces, we can wrap the address path in quotation marks to ensure it changes properly.
  • mkdir <DIR_NAME>: to create a new sub-directory in the current working directory.
  • chmod: which changes the access permissions of a given file/directory.
  • cp: copies files. See flags below.
    • -a /src/. /dest/: recursively copies all contents of the src folder to the dest folder.

To mount a drive:

sudo mount /dev/sda3 /mnt/drv3

System programming

Some helpful syscalls for programming:

  • int open(const char *pathname, int flags, mode_t mode): opens a given file, returns a file descriptor.
    • flags: specify which operations.
      • O_RDWR, O_WRONLY, O_RDWR
      • O_APPEND: moves the position to the end of the file initially.
  • off_t lseek(int fd, off_t offset, int whence): takes file descriptor and changes the position to the offset.
    • whence: specifies how we treat the offset (SEEK_SET, SEEK_CUR, SEEK_END).
  • DIR *opendir(char *path): opens directory.
  • int closedir(DIR *dir): closes directory.

Process control blocks store file tables, which have a table of entries corresponding to each file descriptor. This includes the position, flags, a vnode which points to the file itself (could represent files, pipes, sockets, etc.). Each file descriptor is an index in the table. Each item points to a system-wide, kernel-managed global open file table.

on fork, they share the same GOF entry however, when one advances in position, it also advances for the other (hence why we can “clear” a pipe buffer) opening after fork means multiple GOF entries are created