1. What is a file system and what does an inode store?
A file system controls how data is stored, organized, and retrieved on storage devices, providing the abstraction of files and directories over raw disk blocks.
In Unix/Linux, file metadata lives in the inode (index node): file size, owner UID/GID, permissions (rwx bits), timestamps (access, modify, change), link count, and block pointers (direct, indirect, double-indirect). Crucially, the inode does NOT store the filename — filenames live in directory entries (dentries), which map names to inode numbers. That’s why you can have many names (hard links) pointing to one inode.
2. Compare contiguous, linked, and indexed file allocation.
- Contiguous — the file occupies consecutive blocks. Random access is fast (direct calculation), but growing the file is difficult (may need to move it) and it causes external fragmentation.
- Linked — each block points to the next. Growth is easy and there’s no fragmentation, but random access is slow because you must traverse the chain.
- Indexed — an index block holds all pointers to the file’s data blocks. Supports both random access and growth, with no fragmentation, but pays an index block overhead.
Modern file systems (ext4, NTFS) use extents — a hybrid that describes a file as a list of contiguous block ranges, combining contiguous allocation’s speed with indexed allocation’s flexibility.
3. What’s the difference between a hard link and a symbolic link?
A hard link is another directory entry pointing to the same inode. Deleting the original name doesn’t affect it — the inode stays alive while any link references it. Hard links can’t cross filesystems and typically can’t point at directories.
A symbolic link (symlink) is a special file containing the path to the target. If the target is deleted, the symlink dangles (broken). Symlinks can cross filesystems and point at directories. The interview summary: hard link → another name for the same inode; symlink → a path to a target.
4. How does the OS track free space?
Two common methods: a bit vector — a bitmap where each bit represents a block (1 = free) — which is efficient for locating contiguous free space; and a linked list — each free block points to the next — which is simple but slower for finding a run of contiguous blocks.
The bit vector is the better answer for modern systems: allocation is a matter of finding a run of set bits, which is fast on current hardware.
5. What is seek time and what is rotational latency?
Seek time is the time for the disk arm to move to the correct cylinder — typically 4–10 ms. Rotational latency is the time waiting for the target sector to spin under the head — typically 2–5 ms (a 7200 RPM disk has a 4.17 ms average).
Total access time = seek + rotational latency + transfer time, typically 10–20 ms. I/O is the slowest subsystem in a computer, which is why disk scheduling algorithms exist: they minimize the seek time by ordering requests smartly.
6. Compare the disk scheduling algorithms.
- FCFS — services requests in arrival order. Fair and simple, but has the worst seek time.
- SSTF — services the closest request first. Low average seek time, but can starve edge tracks.
- SCAN (Elevator) — sweeps across the disk servicing requests along the way, then reverses. No starvation, but tracks at the edges wait longer.
- C-SCAN — sweeps in one direction only, then jumps back to the start. More uniform waiting times than SCAN, at the cost of more seeks.
- LOOK / C-LOOK — like SCAN/C-SCAN but reverses direction at the last request instead of the disk end. More efficient.
7. Why is C-SCAN often preferred over SCAN?
C-SCAN provides more uniform waiting times. In SCAN, cylinders near the middle get serviced twice per pass — once in each direction — while cylinders at the edges wait longer. C-SCAN only services requests in one direction and then jumps back, so every cylinder is treated equally across the full sweep.
The uniformity matters for fairness: no request location is systematically favored. The trade-off is slightly more total seek distance than SCAN.
8. What is DMA and why do we use it?
DMA (Direct Memory Access) lets a device controller copy data between the device and memory without involving the CPU for every byte. The CPU tells the DMA controller “copy 4KB from disk to address 0x1000,” then resumes other work; the controller handles the transfer and interrupts the CPU only when done.
Without DMA — programmed I/O (PIO) — the CPU must move every byte from device to memory itself, wasting billions of cycles. DMA is what makes fast I/O possible: the CPU initiates the transfer and gets on with useful work.
9. What’s the difference between buffering and spooling?
Buffering stores data temporarily to handle speed mismatches within a single process — for example, reading a file in chunks while processing it, smoothing out bursts. Storage is memory.
Spooling (Simultaneous Peripheral Operation Online) overlaps the I/O of one process with the computation of another — for example, a print spooler queues print jobs from many processes to disk while one job prints. Storage is disk. The summary: buffering overlaps a process’s I/O with its own computation; spooling overlaps one process’s I/O with another’s computation.
10. What problem does I/O multiplexing solve?
Without multiplexing, a server needs one thread per connection — 10,000 connections means 10,000 threads, and the stack memory plus context-switch overhead becomes prohibitive. I/O multiplexing lets a single thread monitor 10,000 connections and process only the ones that are ready.
The three generations are select() (O(N) scan, capped at 1024 FDs by FD_SETSIZE), poll() (O(N) scan, unlimited FDs), and epoll (Linux, event-driven, O(1) — only ready FDs are returned). kqueue (BSD/macOS) and IOCP (Windows) are the equivalents elsewhere.
11. How does epoll achieve O(1) performance?
epoll is event-driven, not scan-based. Three system calls: epoll_create1() creates the instance, epoll_ctl() registers interest in specific FDs, and epoll_wait() blocks until any registered FD is ready.
The trick: when an FD is registered, the kernel installs a callback in the socket’s wait queue. When the socket becomes ready, the callback adds the FD to a ready list. epoll_wait() just returns that ready list — no scanning of all FDs, so cost is O(number of ready FDs), not O(total FDs). That’s how it scales to hundreds of thousands of connections.
12. What is dual mode operation and why does the OS need it?
Dual mode is the CPU’s separation into kernel mode (ring 0) and user mode (ring 3), enforced by hardware. Kernel mode can execute any instruction, access any memory, and control hardware; user mode has a restricted instruction set and only accesses its own memory.
Without it, any program could read any memory, access any hardware, or corrupt the OS. Dual mode isolates user programs from the kernel and from each other — a crash in user mode doesn’t crash the system, and privileged instructions like I/O port operations, interrupt management, timer configuration, and page-table manipulation can only execute in kernel mode. If a user program tries one, the CPU raises a general protection fault and typically kills the program.
13. Give examples of privileged instructions.
Privileged instructions can only execute in kernel mode: modifying page table registers, disabling/enabling interrupts, setting the system timer, I/O port operations (in/out on x86), memory-management instructions (TLB flush, page-table switch), and switching the mode bit itself.
If a user-mode program attempts any of these, the CPU raises a general protection fault — the OS typically terminates the program. This hardware enforcement, not just OS policy, is what protects the system.
14. How does the system transition from user mode to kernel mode?
Via a trap (software interrupt). The application executes a syscall (or int 0x80) instruction, which atomically: saves the user-mode state (return address, stack pointer), switches the mode bit to kernel (0), and jumps to a predefined handler address in the kernel.
The kernel validates the arguments, performs the request, and switches back to user mode with the return value. The trap is the only sanctioned way into kernel mode — ordinary function calls can’t change privilege levels.
15. What is swap space and what are its trade-offs?
Swap space is a reserved area on disk used as an extension of RAM. When physical memory is full, the OS moves inactive pages to swap, preventing the system from running out of memory entirely.
The trade-off is speed: RAM is ~50ns, swap (disk) is 5ms — roughly 100,000x slower — so swapping heavily causes thrashing. It’s persistent (survives reboot) and cheap (0.10/GBvs 10/GB for RAM). Linux uses a dedicated swap partition or swap file, with the swappiness parameter (0–100) controlling how aggressively the kernel swaps.
16. What is virtualization and what are the two hypervisor types?
Virtualization lets a single physical machine run multiple operating systems simultaneously. Each guest OS thinks it has its own CPU, memory, disk, and network, but the hypervisor (Virtual Machine Monitor) multiplexes the real hardware.
- Type 1 (bare-metal) runs directly on hardware — it IS the OS, handling scheduling and memory for all guests. Near-native performance; used in data centers and cloud (VMware ESXi, Hyper-V, Xen, KVM).
- Type 2 (hosted) runs as an application on an existing host OS, asking the host for resources. Lower performance; used for development and testing (VirtualBox, VMware Workstation).
Hardware-assisted virtualization (Intel VT-x, AMD-V) adds a root/non-root mode so guest code runs directly on the CPU with sensitive instructions auto-trapping to the hypervisor — this is why modern virtualization is fast.
17. How is a container different from a VM?
A VM virtualizes the hardware: each guest includes a full OS with its own kernel, so isolation is strong but the footprint is huge (GBs, minutes to boot). A container virtualizes the OS: all containers share the host kernel and only bundle user-space processes — MBs, seconds to boot.
The trade-off is isolation: containers have moderate isolation because they share a kernel, while VMs are strongly isolated with separate kernels. Containers are what Docker and containerd run; VMs are what KVM and VMware run.
18. What is the difference between authentication and authorization?
Authentication (AuthN) verifies identity — “who are you?” — via something you know (password/PIN), something you have (security key/phone), or something you are (fingerprint/face).
Authorization (AuthZ) determines permissions — “what can you do?” — after identity is established. Models include DAC (file owner decides, Unix rwx), MAC (system-wide policy regardless of owner, SELinux/AppArmor), and RBAC (permissions tied to roles). AuthN always comes before AuthZ. The interview one-liner: authentication answers “who are you?”; authorization answers “what can you do?“
19. What is an Access Control List (ACL)?
An ACL is a list of permissions attached to a file, directory, or object. Each entry (ACE) specifies which user or group has which access rights — read, write, execute, delete.
ACLs provide finer-grained control than standard Unix rwx, which is limited to one owner, one group, and “others.” With an ACL you can grant different permissions to specific individual users beyond the owner. NTFS ACLs are a complex, granular example.
20. Why can’t a standard OS run a self-driving car?
Standard OSes (Linux, Windows) are “best effort” — they optimize throughput and fairness and may pause a critical process for a background update or virus scan. Interrupt latency is variable, potentially high.
An RTOS (QNX, VxWorks) optimizes predictability: priority-based preemptive scheduling, bounded interrupt latency with a guaranteed maximum, and fine-grained kernel preemption. A self-driving car cannot tolerate unpredictable delays — a brake response that arrives late is a crash. That guarantee is exactly what an RTOS provides and a general-purpose OS can’t.
21. What is an interrupt? Explain the types and the ISR flow.
An interrupt is a signal to the CPU that something needs immediate attention, forcing the CPU to pause its current work and run a handler.
Types:
- Hardware interrupt — generated by a device (keyboard, disk, timer) via an interrupt line. The timer interrupt is what drives preemptive scheduling.
- Software interrupt / trap — generated by a running program, either a deliberate
syscall/intinstruction or a fault (divide by zero, page fault).
The ISR (Interrupt Service Routine) flow:
- A device raises the interrupt line; the CPU finishes the current instruction.
- The CPU saves the current context (registers, return address).
- It looks up the handler in the interrupt vector table and jumps to the ISR.
- The ISR runs (in kernel mode, with interrupts typically masked), handles the event, and sends an end-of-interrupt (EOI).
- The CPU restores the saved context and resumes the interrupted work.
Interrupt vs trap vs exception:
- Interrupt — asynchronous, from hardware (can happen anytime).
- Trap — synchronous, intentional, from a program (a syscall); also called a software interrupt.
- Exception — synchronous, unintentional fault (divide by zero, invalid memory access). A fault that can’t be fixed becomes an abort.
The summary: interrupts are asynchronous hardware signals; traps are intentional software signals; exceptions are unintentional faults. Interrupts keep the CPU responsive without polling — it doesn’t constantly check devices, it waits to be told.
22. What are the RAID levels?
RAID (Redundant Array of Independent Disks) combines multiple disks to improve performance (parallel I/O) and reliability (redundancy).
- RAID 0 (striping) — data split across all disks in blocks. Full performance, no redundancy — one disk fails, all data is lost.
- RAID 1 (mirroring) — every disk is duplicated on a second. Full redundancy (survives one disk failure), but halves usable capacity and write speed is the slowest disk.
- RAID 5 (striped with parity) — data striped across disks with one disk’s worth of parity distributed among them. Survives one disk failure with N disks and N−1 usable space. Best balance of capacity, speed, and reliability — the common enterprise choice.
- RAID 6 (striped with dual parity) — two parity blocks; survives two disk failures, at the cost of more overhead.
- RAID 10 (RAID 1+0) — mirroring then striping: a striped set of mirrored pairs. Strong performance and redundancy (survives any disk in each mirror), but half capacity.
The interview one-liners: RAID 0 = speed no safety; RAID 1 = mirror, safe but ½ space; RAID 5 = striping + one parity, survives one failure; RAID 6 = two parities, survives two; RAID 10 = mirror + stripe, fast and safe. Redundancy adds fault tolerance; the “rebuild” is copying parity/duplicated data onto a replacement disk.
23. What is journaling and why do file systems use it?
Journaling is a technique that makes a file system crash-consistent: it records an intent — a journal (log) — before applying changes, so it can recover cleanly after a power loss or crash.
The flow (write-ahead logging):
- Before modifying the file system, the OS appends a journal record describing the intended change.
- The change is applied to the actual data structures.
- Once complete, the journal entry is marked committed (and later discarded).
On a crash, the file system replays the journal: committed-but-unfinished changes are completed; uncommitted ones are rolled back. Without journaling, a crash mid-write could leave the file system corrupt (e.g. an inode pointing to blocks that were never written).
The write order — journal first, then data — is what guarantees recovery. ext3/ext4 (Linux) and NTFS (Windows) are journaled file systems; this is why they survive sudden power loss far better than older FAT, which has no journal and can be left inconsistent. The trade-off is extra disk writes for the journal, which journaling systems reduce by journaling only metadata by default rather than the full data.
24. What is a device driver and what is memory-mapped I/O?
A device driver is kernel software that translates generic OS requests into the commands a specific device controller understands. The OS exposes a uniform interface (open, read, write) to applications; the driver knows the exact protocol of its hardware. An app writes a file → the file system passes a block request to the driver → the driver issues the precise sector/timing commands to the disk controller. A buggy driver runs with high privilege, which is why it can crash the whole system.
The OS talks to hardware registers in one of two ways:
- Port-mapped I/O (PIO / isolated I/O) — the CPU uses special
in/outinstructions with a separate I/O address space (x86). Each device has an I/O port number. - Memory-mapped I/O (MMIO) — device registers are mapped into the regular memory address space; the CPU writes to them with ordinary load/store instructions. No special instructions needed, but it consumes address space and can interact with caching.
The interview summary: a driver is the per-device translator behind the OS’s uniform I/O interface; port-mapped I/O uses dedicated instructions, memory-mapped I/O uses normal memory loads/stores to talk to devices.
25. What are signals and how do they work?
A signal is a small, asynchronous notification delivered to a process — a software event sent either from the kernel or from another process. Examples: SIGINT (Ctrl+C), SIGKILL, SIGSEGV (segmentation fault), SIGCHLD (child terminated).
Generation — a signal is raised by an event (a keypress, an error, another process via kill(), or the shell). Delivery — the kernel delivers it to the target process, which by default either terminates, ignores it, or stops.
A process can install a handler with signal()/sigaction() to run custom code when a specific signal arrives; the default action is used otherwise. Masking blocks delivery of chosen signals (deferred until unmasked) — used to protect critical sections from interruption.
Key safety rule: the handler runs asynchronously, interrupting the process at any instruction, so it may only call async-signal-safe functions (like write, _exit), never unsafe ones like malloc or printf — calling a non-reentrant function from a handler is undefined behavior. SIGKILL and SIGSTOP cannot be caught or masked.
26. Compare FAT, NTFS, and inode-based file systems.
- FAT (File Allocation Table) — an old, simple file system (FAT16/FAT32) that tracks each file’s blocks in a table. Widely compatible across OSes, but has no journaling, no permissions, and file-size limits. Simple and cheap to implement.
- NTFS — Windows’ modern journaled file system. Supports ACLs and security permissions, file compression and encryption, journaling for crash recovery, and very large volumes. More overhead than FAT.
- Inodes (ext2/ext3/ext4, UFS) — the Unix approach. Each file has an inode — a metadata record (size, owner, permissions, timestamps, block pointers) stored separately from the data. Directories are just name→inode-number mappings. Supports hard links (multiple names → one inode) and efficient lookup. ext4 adds extents and journaling.
| Structure | Key strengths | Weaknesses | |
|---|---|---|---|
| FAT | Allocation table | Compatibility, simple | No journaling, no permissions |
| NTFS | Journaled, ACLs | Security, durability, large files | Heavier overhead |
| Inode | Inode per file | Fast, hard links, flexible | Metadata complexity |
The interview takeaway: FAT = simple compatibility; NTFS = secure, journaled, Windows; inode = metadata-per-file, the Unix standard. Modern Linux (ext4) combines inode structure with extents and journaling.
Premium Content
Unlock File Systems, I/O & Advanced Topics and all premium lessons with a subscription.
From ₹199.99/year — See plans