OSOperating Systems · Lesson 5 of 7

Files, Descriptors & Filesystems

Unix's boldest simplification: everything is a file. Documents, your terminal, network sockets, even random numbers — all read and written through the same tiny interface.

A filesystem maps names to data: directories are lists of name-to-inode entries, and an inode holds a file's metadata (size, owner, permissions, timestamps) plus pointers to its data blocks on disk. The filename is not the file — several names can point to one inode (hard links), and a file deleted while open lives on until the last descriptor closes.

Bash
ls -li                    # -i shows inode numbers
stat README.md            # everything the inode knows

# Permissions: read/write/execute for user/group/other
# rwxr-xr--  =  owner: rwx, group: r-x, others: r--
chmod u+x script.sh       # let the owner execute
chmod 644 notes.txt       # rw-r--r-- in octal shorthand

# 'Everything is a file':
cat /dev/urandom | head -c 16 | xxd    # random bytes
echo hi > /dev/null                    # the bit bucket
cat /proc/cpuinfo | head -5            # kernel state as files
Python
# File descriptors: small integers naming open files.
# Every process starts with three:
#   0 = stdin, 1 = stdout, 2 = stderr
import os
fd = os.open("data.txt", os.O_WRONLY | os.O_CREAT)
print(fd)                 # 3 — next free number
os.write(fd, b"hello\n")
os.close(fd)

# Shell redirection is just descriptor surgery:
#   ./prog > out.txt 2>&1
# means: point fd 1 at out.txt, then point fd 2
# wherever fd 1 points. That's the whole trick.
✦ Tip
Writes are buffered at multiple layers — your language's library, then the kernel's page cache. 'Saved' data may sit in RAM for seconds before reaching disk; that's what fsync() and safe-save patterns (write temp file, fsync, rename) are for. Databases obsess over this — now you know why.