OPERATING SYSTEMS / 6. FILE SYSTEMS & I/O
File Systems, I/O & Storage
How data is organized on disk and how the OS reads and writes it
EXPLANATION
A file system is the data structure that organizes bytes on a storage device into files and directories. Without a file system, a disk is just a flat sequence of blocks with no meaning. Everything is a file (Unix philosophy): • Regular files, directories, symbolic links • Block devices (/dev/sda — raw disk access) • Character devices (/dev/tty — terminals, /dev/null, /dev/urandom) • Named pipes (FIFOs) • Sockets (yes, even network connections can be represented as files) • /proc and /sys virtual filesystems (kernel data structures exposed as files) The VFS (Virtual File System) layer: The kernel's VFS is an abstraction layer that provides a unified API (open, read, write, close, mkdir, stat) to all file systems. Whether the underlying storage is ext4, NTFS, btrfs, NFS, or procfs — user programs always use the same syscalls. The VFS dispatches to the right implementation. ext4 (the most common Linux filesystem): • Disk is divided into blocks (4 KB each by default) • Inodes: every file has an inode — a data structure storing metadata: - File type (regular, directory, symlink, device) - Permissions (rwxrwxrwx) and owner (UID, GID) - Size, timestamps (created, modified, accessed) - Pointers to data blocks The inode does NOT contain the filename! Filenames live in directories. • Directories: a file whose content is a list of (filename → inode number) pairs • Hard links: two directory entries pointing to the same inode. Deleting one doesn't delete the file — only when reference count reaches 0 does the inode get freed • Symbolic links: a file whose content is a path string. Like a shortcut The I/O path (reading a file): ① User calls read(fd, buf, size) — syscall ② Kernel checks page cache — is this data already in RAM? ③ If yes (cache hit) — copy from page cache to user buffer → done ④ If no (cache miss) — submit I/O request to block device driver ⑤ Driver sends command to disk (NVMe, SATA) ⑥ Disk hardware reads data → DMA into kernel memory (page cache) ⑦ Kernel copies from page cache to user buffer ⑧ Return to user space Page cache: the kernel caches file contents in RAM. Subsequent reads of the same data skip the disk entirely. Writes also go to the page cache first (write buffering) — flushed to disk later by pdflush/kdmflush threads (or on fsync()). File descriptors: every open file is represented by a file descriptor (small integer). fd 0 = stdin, 1 = stdout, 2 = stderr. open() returns a new fd. File descriptors are entries in the process's file descriptor table, which point to kernel file objects. journaling in ext4: before modifying disk structures, ext4 writes a journal entry. If the system crashes mid-write, the journal is replayed on next mount to restore consistency. Prevents filesystem corruption.
DIAGRAM
EXT4 DISK LAYOUT:
┌──────────────┬───────────────────────────────────────┐
│ Superblock │ Block Group 0 │ Block Group 1 ... │
│ (metadata │ │ │
│ about FS) │ Inode Table │ Data Blocks │
└──────────────┴─────────────────────────────────────────┘
INODE STRUCTURE:
Inode #42:
├── type: regular file
├── permissions: rw-r--r-- (644)
├── owner: uid=1000 (kamran)
├── size: 4096 bytes
├── mtime: 2025-03-14 16:52
└── data block pointers: [block 500, block 501, ...]
DIRECTORY = file containing name→inode mappings:
/home/kamran/ (inode 42)
├── "." → inode 42 (self)
├── ".." → inode 2 (parent)
├── "deepdocs" → inode 1337
└── "resume.pdf" → inode 9999
I/O PATH:
read(fd) → VFS → Page Cache (RAM)
↓ (cache miss)
Block Driver → NVMe → Disk
↑
DMA → Page Cache → user bufferCODE