Operating System Interview Questions

Check the list of Operating System interview questions covering various topics like definitions, memory management, processes, file systems, scheduling algorithms, and advanced concepts, which will help you prepare well for interviews. This will be useful for both beginners and experienced professionals.

What is an Operating System?

An Operating System (OS) is system software that manages computer hardware, software resources, and provides common services for computer programs. It acts as an intermediary between users and the computer hardware.

Why Operating System is Important from a Placements Perspective

Having a strong understanding of Operating System concepts is crucial for technical interviews, particularly for roles related to system-level programming, software engineering, and IT infrastructure. Here's why it should be a priority for you:

  • Core Knowledge: Operating systems are fundamental to understanding how computer systems function, and many technical interviews test your knowledge of OS concepts.
  • Real-World Relevance: OS knowledge is crucial in handling memory, processes, and scheduling in real-world applications and server environments.
  • Performance Tuning: An understanding of OS concepts helps in optimizing system performance, especially for backend or embedded systems roles.
  • Problem-Solving Skills: OS interview questions often involve problem-solving in areas like resource allocation, synchronization, and deadlock handling, showcasing your analytical skills.
  • Industry Demand: Professionals who are proficient in OS concepts, especially in areas like system design and multi-threading, are in high demand across various industries, including tech, embedded systems, and telecommunications.

1. What is an Operating System?

An Operating System (OS) is system software that acts as an intermediary between computer hardware and the user. It manages hardware resources and provides a platform for application programs to run.

Without an OS, users would need to interact directly with hardware using complex machine-level instructions. The OS abstracts this complexity and provides a clean, consistent interface.

Key characteristics:

  • First program loaded into memory when a computer starts (after the bootstrap)
  • Remains in memory throughout the computer's operation
  • Controls all other programs running on the computer

Examples: Windows 11, macOS, Linux (Ubuntu, Fedora), Android, iOS.


2. Main Functions of an Operating System

Process Management — Creates, schedules, and terminates processes. Allocates CPU time using algorithms like FCFS, Round Robin, and Priority Scheduling.

Memory Management — Tracks every byte of RAM, allocates/deallocates memory as processes start and stop, and implements virtual memory.

File System Management — Organizes data into files and directories. Handles creation, deletion, reading, writing, and permissions.

Device Management — Controls communication between software and hardware devices (keyboard, mouse, disk, printer) through device drivers.

Security & Access Control — Enforces authentication and authorization, manages user accounts, permissions, and auditing.

Networking — Provides TCP/IP networking stack for local and internet communication.

User Interface — Offers CLI (Command Line Interface) or GUI (Graphical User Interface).

Error Detection & Handling — Monitors the system for hardware/software errors and responds appropriately.


3. Monolithic vs. Microkernel Architecture

Monolithic Kernel

The entire OS runs as a single large program in kernel space. All services — process management, memory, file systems, drivers — are bundled together with full hardware privileges.

  • Fast communication between components (direct function calls)
  • A bug in any component can crash the entire system
  • Examples: Linux, Unix, MS-DOS

Microkernel

The kernel is stripped to only essentials: IPC, basic scheduling, and memory management. Everything else runs in user space as separate server processes.

  • Components communicate via message passing
  • Crashed server doesn't bring down the kernel
  • Performance overhead due to frequent context switches and IPC
  • Examples: Mach, QNX, MINIX
FeatureMonolithicMicrokernel
SizeLargeSmall
PerformanceHigherLower (IPC overhead)
StabilityLowerHigher
ExtensibilityHarderEasier

4. What is a Kernel?

The kernel is the core component of an OS — loaded first at boot and stays in memory at all times. It acts as a bridge between software applications and hardware.

Core responsibilities:

  • CPU Scheduling — decides which process gets CPU and for how long
  • Memory Management — allocates and deallocates physical and virtual memory
  • Device Management — interacts with hardware through drivers
  • System Calls — provides safe interface for user programs to request OS services
  • Interrupt Handling — responds to hardware and software interrupts

Types: Monolithic (Linux), Microkernel (QNX), Hybrid (Windows NT, macOS XNU), Exokernel, Nanokernel.


5. User Mode vs. Kernel Mode

Modern CPUs operate in two privilege levels to protect the OS from misbehaving applications.

User Mode — Programs run here with restricted access. They cannot directly access hardware or protected memory. A crash affects only the running application.

Kernel Mode — The OS kernel runs here with full, unrestricted hardware access. A crash or bug can bring down the entire system (kernel panic / BSOD).

Mode Switching: When a user program needs an OS service, it issues a system call → CPU switches to kernel mode → executes service → returns to user mode.

AspectUser ModeKernel Mode
Privilege LevelLowHigh
Hardware AccessRestrictedUnrestricted
Memory AccessOwn process onlyFull system
Crash ImpactApplication onlyEntire system
ExamplesBrowsers, editorsOS kernel, drivers

6. What is IPC? Different IPC Mechanisms

IPC (Inter-Process Communication) provides mechanisms that allow processes running in isolated memory spaces to share data or coordinate actions.

IPC Mechanisms:

  • Pipes — unidirectional byte stream; anonymous pipes require parent-child relationship; named pipes (FIFOs) allow unrelated processes
  • Message Queues — kernel-stored linked list of messages; supports FIFO and priority ordering
  • Shared Memory — fastest IPC; processes map same physical memory region; requires explicit synchronization
  • Semaphores — integer-based synchronization using wait() and signal() operations
  • Sockets — communication on same machine or across a network (TCP/UDP)
  • Signals — lightweight async notifications (SIGKILL, SIGINT, SIGCHLD)
  • Memory-Mapped Files — file mapped into address space; multiple processes share it
  • RPC (Remote Procedure Call) — call a function in another process or machine as if local

7. Main Purpose of OS & Types

Main Purpose

The OS manages hardware resources (CPU, memory, storage, I/O), provides a user interface, executes and manages programs, and ensures security and protection.

Types of Operating Systems

TypeDescriptionExample
Batch OSProcesses jobs in batches without user interactionEarly IBM mainframes
Time-Sharing OSMultiple users share CPU via rapid switchingUNIX
Distributed OSManages networked computers as a single systemAmoeba, Plan 9
Real-Time OSProcesses inputs within strict time deadlinesVxWorks, FreeRTOS
Embedded OSOptimized for limited hardware resourcesAndroid, Embedded Linux
Network OSFile/printer sharing over networkWindows Server, NetWare
Mobile OSDesigned for touchscreen devices with limited batteryAndroid, iOS
Single-User OSOne user at a timeMS-DOS
Multi-User OSMultiple simultaneous usersLinux, UNIX

8. Benefits of a Multiprocessor System

A multiprocessor system contains two or more CPUs sharing common bus, memory, and I/O devices.

1. Increased Throughput — Multiple CPUs execute tasks truly simultaneously, boosting overall performance.

2. Economy of Scale — Shared peripherals, storage, and power supplies reduce cost compared to separate single-processor systems.

3. Fault Tolerance — If one CPU fails, others continue. Critical for banking, hospitals, air traffic control.

4. Better Resource Utilization — Workloads distributed across CPUs so no single processor is a bottleneck.

5. Parallel Computing — Compute-intensive tasks (ML, video rendering, simulations) split across CPUs for faster completion.

Types: SMP (all equal CPUs, most common), AMP (master-slave), NUMA (each CPU has local memory).


9. RAID Structure & Levels

RAID (Redundant Array of Independent Disks) combines multiple physical drives into one logical unit using striping (performance), mirroring (redundancy), and parity (error correction).

RAID 0 — Striping: Data split across all disks. Max performance, zero fault tolerance. One disk failure = total data loss.

RAID 1 — Mirroring: Data written identically to 2+ disks. Excellent reliability; 50% storage efficiency.

RAID 5 — Distributed Parity: Data + parity spread across all disks. Survives 1 disk failure. Most popular for servers. Minimum 3 disks.

RAID 6 — Double Parity: Like RAID 5 but survives 2 simultaneous disk failures. Minimum 4 disks.

RAID 10 (1+0) — Mirror + Stripe: Combines RAID 1 and 0. High performance + fault tolerance. 50% efficiency.

RAID LevelMin DisksFault ToleranceStorage Efficiency
RAID 02None100%
RAID 121 disk50%
RAID 531 disk(n-1)/n
RAID 642 disks(n-2)/n
RAID 1041 per mirror50%

10. What is GUI?

GUI (Graphical User Interface) allows users to interact with a computer using visual elements — windows, icons, menus, and buttons — rather than typing text commands.

Pioneered by Xerox PARC in the 1970s, popularized by Apple Macintosh (1984) and Microsoft Windows.

Key components: Windows, Icons, Menus, Buttons, Scroll Bars, Dialog Boxes, Desktop.

Benefits: User-friendly, intuitive for beginners, supports multitasking, visual error feedback.

Limitations: Resource-heavy compared to CLI, less efficient for scripting and automation tasks.

Examples: Windows 11 shell, macOS Aqua, GNOME/KDE on Linux, Android touch UI.


11. What is a Pipe and When is it Used?

A pipe is a unidirectional IPC mechanism where the output of one process becomes the input of another process. Data flows in FIFO order.

Anonymous Pipes — Created with pipe(). Exist only in memory, require a parent-child relationship. Example: ls | grep .txt

Named Pipes (FIFOs) — Created with mkfifo(). Have a filesystem entry; allow communication between unrelated processes. Persist until deleted.

When used:

  • Shell pipelines (chaining commands)
  • Producer-Consumer patterns
  • Data filtering through a series of transformations
  • Simple, lightweight one-directional IPC

Limitations: Unidirectional; anonymous pipes require parent-child relationship; byte-stream only (no message boundaries).


12. Operations on a Semaphore

A semaphore is an integer-based synchronization primitive introduced by Edsger Dijkstra.

wait() / P() / down()

wait(S): while S <= 0 { block }; S = S - 1

Decrements value. If S = 0, the process blocks until a resource is available.

signal() / V() / up()

signal(S): S = S + 1

Increments value. Unblocks one waiting process if any exist.

Types:

  • Binary Semaphore — value 0 or 1; acts like a mutex for mutual exclusion
  • Counting Semaphore — value 0 to N; manages a pool of N identical resources

Both operations must be atomic to prevent race conditions. Modern systems also support: Initialize, Timed Wait, and Try Wait (non-blocking attempt).


13. What is a Bootstrap Program?

A bootstrap program (bootloader) is the first program that runs when a computer powers on. It initializes hardware and loads the OS kernel into memory.

Boot sequence:

  1. CPU executes from fixed ROM address → BIOS/UEFI firmware
  2. BIOS performs POST (Power-On Self-Test) — checks CPU, RAM, keyboard, storage
  3. Locates bootloader on disk (MBR or EFI System Partition)
  4. Bootloader loads OS kernel into RAM and transfers control
  5. Kernel initializes all subsystems and starts first user-space process (init/systemd)

Characteristics: Stored in ROM/flash (non-volatile), must work without OS support, very small in size.

Examples: GRUB2 (Linux), Windows Boot Manager, Das U-Boot (embedded systems).


14. Explain Demand Paging

Demand paging loads process pages into physical memory only when they are accessed, not all at startup. It is the foundation of virtual memory systems.

How it works:

  • Each page has a valid/invalid bit in the page table
  • Invalid = page not in memory
  • Accessing an invalid page triggers a page fault (hardware interrupt)
  • OS finds a free frame (or evicts one using LRU/FIFO/Optimal)
  • Loads the required page from disk into the frame
  • Updates page table → restarts the faulting instruction

Benefits:

  • Faster program startup
  • Programs can be larger than physical RAM
  • Only actively used pages occupy RAM
  • More processes fit in memory simultaneously

Drawbacks: Page fault overhead (disk I/O is slow); risk of thrashing when too many faults occur.


15. What is RTOS?

RTOS (Real-Time Operating System) is designed to process data and respond to inputs within strict, guaranteed time deadlines. Correctness depends on both the logical result AND the time it is produced.

Types:

  • Hard Real-Time — missing deadline = catastrophic failure. Examples: pacemakers, aircraft flight control, nuclear plant monitoring
  • Soft Real-Time — missing deadline = degraded performance but not failure. Examples: video streaming, online gaming
  • Firm Real-Time — missed deadline = result is useless. Examples: financial trading systems

Key Characteristics:

  • Deterministic behavior — tasks complete within predictable time bounds
  • Priority-based preemptive scheduling
  • Minimal interrupt latency
  • Small memory footprint
  • No or minimal virtual memory (page faults add unpredictable delay)

Examples: VxWorks, FreeRTOS, QNX, RTEMS, Zephyr.


16. What is Process Synchronization?

Process synchronization is the coordination of concurrent processes that share resources to prevent race conditions and ensure data consistency.

Race Condition — When multiple processes access shared data concurrently, the outcome depends on the execution order, leading to unpredictable, incorrect results.

Critical Section Problem requires three conditions:

  • Mutual Exclusion — only one process in CS at a time
  • Progress — decision to enter made in finite time
  • Bounded Waiting — finite limit on how long a process waits

Synchronization Mechanisms: Mutex Locks, Semaphores, Monitors, Condition Variables, Spinlocks.

Classic Problems: Producer-Consumer, Readers-Writers, Dining Philosophers.


17. Why is the Operating System Important?

  • Hardware Abstraction — hides hardware complexity; developers write for OS APIs, not raw hardware
  • Resource Management — fairly allocates CPU, memory, storage, and I/O
  • Security & Privacy — enforces access controls, authentication, and process isolation
  • Multitasking — runs dozens of programs simultaneously via fast context switching
  • Application Platform — provides system calls and APIs for software development
  • Error Management — detects and handles hardware/software errors gracefully
  • Standardization — consistent interface (POSIX, WinAPI) enables software portability
  • Networking — built-in TCP/IP stack enables internet and local network communication

18. Main Memory vs. Secondary Memory

Main Memory (RAM) is the computer's primary working storage. The CPU directly accesses it. It is volatile — data is lost on power off.

Secondary Memory is persistent storage (HDDs, SSDs, USB drives). CPU cannot access it directly — data must be copied to RAM first. Non-volatile — data survives power off.

FeatureMain Memory (RAM)Secondary Memory
SpeedVery fast (nanoseconds)Slow (ms for HDD, µs for SSD)
VolatilityVolatileNon-volatile
CapacityGBs (4–128 GB)TBs (hundreds of GB to TBs)
CPU AccessDirect via memory busVia I/O controller
CostHigh per GBLow per GB
PurposeActive programs/dataLong-term data storage

19. What are Overlays?

Overlays are a technique for running programs larger than available physical RAM by loading only the currently needed section into memory, overwriting previously loaded sections when they are no longer needed.

How it works:

  • Program split into a root section (always in memory) + multiple overlay sections
  • The root contains the overlay manager
  • When code from an unloaded overlay is needed, the manager loads it from disk, overwriting an unused overlay
  • Only the active portion exists in RAM at any time

Key characteristics:

  • Managed manually by the programmer — this distinguishes it from virtual memory (which is OS-managed)
  • Predecessor to modern virtual memory
  • Used widely in MS-DOS era programs
  • Complex to implement correctly; replaced by automatic virtual memory systems

20. Top 10 Operating System Examples

  1. Windows 11 — world's most used desktop OS; homes, businesses, gaming
  2. macOS Sonoma — Apple's Unix-based OS; elegant design, tight hardware integration
  3. Ubuntu Linux — most popular Linux distro; free, open-source, community-driven
  4. Android — powers 70%+ of smartphones; based on Linux kernel
  5. iOS — Apple's mobile OS for iPhone/iPad; known for performance and security
  6. Fedora Linux — cutting-edge, developer-focused, sponsored by Red Hat
  7. Chrome OS — browser-centric OS for Chromebooks; supports Android apps
  8. FreeBSD — enterprise-grade Unix-like OS; used in macOS, Netflix, PlayStation
  9. Windows Server 2022 — enterprise server OS; Active Directory, Hyper-V, Azure integration
  10. FreeRTOS — open-source RTOS for microcontrollers and IoT devices

21. What is Multitasking?

Multitasking is the OS's ability to execute multiple processes seemingly simultaneously on a single CPU by rapidly switching between them, creating the illusion of parallelism.

Types:

  • Preemptive Multitasking — OS forcibly interrupts a running process after its time quantum expires and switches to the next process. Used by all modern OSes (Linux, Windows, macOS).
  • Cooperative Multitasking — Process voluntarily yields the CPU. One misbehaving process can freeze the system. Used by early Windows 3.x, classic Mac OS.

How it works: OS maintains a ready queue → scheduler picks next process → context switch (saves/restores registers and PC) → new process resumes.

Benefits: Better CPU utilization, improved user experience, efficient I/O handling.


22. What is Caching?

Caching stores copies of frequently accessed data in faster storage to reduce future access time. It exploits the principle of locality of reference.

Levels of caching:

  • CPU Cache (L1/L2/L3) — on-chip; sub-nanosecond; stores RAM data for fast CPU access
  • TLB (Translation Lookaside Buffer) — hardware cache for page table entries
  • Disk Cache (Buffer Cache) — OS keeps recently read/written disk blocks in RAM
  • Web/Browser Cache — stores web resources locally to avoid re-downloading
  • DNS Cache — stores resolved domain names to avoid repeated DNS lookups

Cache Replacement Policies:

  • LRU — evict least recently used (best general-purpose policy)
  • FIFO — evict oldest entry
  • LFU — evict least frequently used
  • Optimal — evict item not needed for longest time (theoretical benchmark)

23. What is Spooling?

SPOOL (Simultaneous Peripheral Operations On-Line) is a technique where data is temporarily buffered to disk so that slow I/O devices (like printers) don't block faster processes.

How it works (Printer Example):

  1. Process writes print data to a spool file on disk instead of waiting for the printer
  2. Process continues executing immediately
  3. A background spooler daemon manages the print queue
  4. When the printer is ready, the daemon reads from the spool and sends data at the printer's pace
  5. Multiple jobs from different processes are queued and printed one after another

Characteristics: Decouples fast processes from slow devices; enables multiple jobs for one device; jobs stored non-volatilely on disk.

Applications: Print queues, email spooling, batch job processing.


24. Functionality of an Assembler

An assembler converts assembly language (human-readable mnemonics: MOV, ADD, JMP) into machine code (binary) that the CPU can execute directly.

How it works — Two Passes:

  • Pass 1: Scans source code, builds a symbol table (labels → addresses), calculates instruction sizes
  • Pass 2: Translates mnemonics to binary opcodes, resolves symbol references using the symbol table, generates the object file

Types: Single-pass (fast but struggles with forward references), Two-pass (most common), Cross assembler (generates code for a different architecture), Macro assembler (supports reusable code blocks).

FeatureAssemblerCompilerInterpreter
InputAssembly languageHigh-level languageHigh-level language
OutputMachine codeMachine code/bytecodeNo persistent output
TranslationOne-to-one (mostly)Many-to-manyLine by line at runtime

25. What are Interrupts?

An interrupt is a signal to the CPU that an event needs immediate attention. The CPU pauses current execution, saves its state, runs the ISR (Interrupt Service Routine), then resumes.

Types:

  • Hardware Interrupts — generated by devices (keyboard, mouse, disk I/O completion, timer). Asynchronous — can happen anytime.
  • Software Interrupts (Traps) — intentional (system calls like int 0x80) or error-based (division by zero, segfault)
  • Maskable — can be disabled by CPU; used for regular I/O
  • Non-Maskable (NMI) — cannot be disabled; used for critical hardware failures

Interrupt Handling Process:

  1. Interrupt occurs → CPU finishes current instruction
  2. Saves state (registers, PC) to the stack
  3. Looks up Interrupt Vector Table (IVT) for ISR address
  4. Executes ISR
  5. Restores saved state → resumes interrupted program
AspectInterruptPolling
CPU UsageEfficient (event-driven)Wasteful (constant checking)
Response TimeFastDepends on poll frequency
Use CaseAll modern OS I/OSimple embedded systems

26. What is Preemptive Multitasking?

Preemptive multitasking is when the OS forcibly takes control of the CPU from a running process — without its consent — when its time quantum expires, and gives the CPU to another process.

How it works:

  1. OS assigns a time quantum (10–100 ms) to each process
  2. A hardware timer fires an interrupt when the quantum expires
  3. The scheduler saves the current process's state (context switch) and selects the next process
  4. The preempted process returns to the ready queue and resumes later

Why it matters: Without preemption, a process with an infinite loop would freeze the entire system. Preemption guarantees fairness, responsiveness, and system stability.

FeaturePreemptiveCooperative
CPU SwitchOS-controlled (timer)Process-controlled (voluntary yield)
FairnessGuaranteedNot guaranteed
StabilityHighLow (one bad process = freeze)
ExamplesLinux, Windows, macOSEarly Windows 3.x, classic Mac OS

27. What is a Zombie Process?

A zombie process is one that has finished execution but still has an entry in the process table because its parent process has not yet called wait() to read its exit status.

How it's created:

  1. Child calls exit() — OS frees its resources but keeps its process table entry (holds PID, exit code, CPU stats)
  2. OS sends SIGCHLD to the parent
  3. If parent never calls wait() — the child remains a zombie indefinitely

Characteristics:

  • Consumes no CPU or memory (only a process table slot)
  • Cannot be killed with kill -9 (already dead)
  • Dangerous at scale — a full process table prevents new process creation

Fix: Parent calls wait() after each child exits, or kill the parent so init/systemd adopts and reaps the zombies. Detect on Linux: ps aux | grep 'Z'


28. What are Orphan Processes?

An orphan process is a still-running process whose parent process has terminated before it finishes execution.

What happens: In Unix/Linux, orphans are adopted by init/systemd (PID 1), which becomes their new parent and automatically reaps them when they finish.

Intentional Orphans (Daemons): Programmers deliberately create orphans to run background services:

  1. Parent forks a child
  2. Parent exits immediately
  3. Child is adopted by init and runs indefinitely in the background
AspectZombieOrphan
Process StateDead (finished)Still running
Parent StateAlive but hasn't called wait()Dead (terminated)
Resource UseMinimal (only process table entry)Full (CPU, memory)
ResolutionParent calls wait() or is killedAdopted by init/systemd

29. Starvation and Aging

Starvation is when a low-priority process is indefinitely denied CPU time because higher-priority processes continuously arrive and get scheduled ahead of it.

Causes: Priority scheduling (low-priority jobs never run), SJF (long jobs never run if short jobs keep arriving), resource contention.

Aging is the solution — the OS gradually increases the priority of waiting processes over time.

How aging works:

  • Every fixed time interval, the OS increments priority of all waiting processes
  • Eventually even the lowest-priority process accumulates enough priority to run
  • After execution, priority resets to its original value

Example: Priority starts at 0, gains +1 per minute → after 100 minutes it becomes the highest priority and gets scheduled.


30. What is a Dispatcher?

The dispatcher is the OS module that actually gives CPU control to the process selected by the scheduler. The scheduler decides who runs; the dispatcher does the switch.

Functions of the Dispatcher:

  1. Context Switching — saves current process's CPU state (registers, PC) into its PCB; loads next process's state
  2. Mode Switch — transitions CPU from kernel mode to user mode
  3. Jump to Correct Location — sets PC to where the new process was last paused

Dispatcher vs. Scheduler:

AspectSchedulerDispatcher
RoleDecides which process runs nextActually performs the CPU switch
FrequencyCalled at scheduling eventsCalled every context switch
OutputSelected process IDCPU handed to selected process

The dispatcher is performance-critical — it runs on every context switch, so its code must be extremely fast.


31. Define Dispatch Latency

Dispatch latency is the total time taken by the dispatcher to stop one process and start another — from the moment a new process is selected to the moment it begins executing on the CPU.

Components:

  • Context Switch Time — save current process state + load next process state from PCBs
  • Mode Switch Time — transition from kernel mode to user mode
  • Cache/TLB Flush Overhead — switching processes invalidates TLB entries and caches, causing cold-start overhead

Why it matters: Every context switch wastes CPU time on overhead. In real-time systems, if dispatch latency is too high, deadlines cannot be met. Typical value: a few microseconds to tens of microseconds in modern systems.

How to minimize: Keep dispatcher code lean, use hardware-assisted context switching, design efficient PCB structures, use RTOS kernels for hard real-time tasks.


32. Goals of CPU Scheduling

CPU scheduling algorithms are designed to balance multiple objectives:

  1. Maximum CPU Utilization — keep CPU busy at all times (target: 40–90%)
  2. Maximum Throughput — complete as many processes per unit time as possible
  3. Minimum Turnaround TimeTurnaround = Completion Time − Arrival Time
  4. Minimum Waiting TimeWaiting = Turnaround Time − Burst Time
  5. Minimum Response Time — time from request submission to first response (critical for interactive systems)
  6. Fairness — every process gets a reasonable share of CPU; no starvation
  7. Balanced Resource Use — keep CPU, memory, I/O devices all utilized evenly

Trade-offs: Maximizing throughput (favor short jobs) conflicts with fairness (long jobs starve). Minimizing response time conflicts with maximizing CPU utilization. Different algorithms prioritize different goals.


33. What is a Critical Section?

A critical section is a segment of code where a process accesses shared resources (variables, data structures, files, devices) that must not be simultaneously accessed by more than one process.

Structure:

Entry Section        ← request permission to enter
Critical Section     ← access shared resources
Exit Section         ← release lock / signal others
Remainder Section    ← rest of the process's work

Three Requirements for a Valid Solution:

  • Mutual Exclusion — only one process in CS at a time
  • Progress — if no process is in CS, a decision on who enters must be made in finite time
  • Bounded Waiting — after requesting entry, a process must enter within a finite number of others' turns

Example: In banking, if two processes simultaneously read, add, and write a balance without synchronization, one update will be lost (race condition).


34. Names of Synchronization Techniques

Hardware-Based:

  • Test-and-Set (TSL), Compare-and-Swap (CAS), Fetch-and-Add, Disable Interrupts

Software-Based:

  • Peterson's Algorithm (2 processes), Dekker's Algorithm (2 processes), Lamport's Bakery Algorithm (N processes)

OS-Provided Primitives:

  • Mutex Locks, Semaphores (binary and counting), Monitors, Condition Variables, Spinlocks, Read-Write Locks, Barriers

Message-Passing Based:

  • Message Queues, Mailboxes, Pipes, Sockets

Transactional Memory:

  • Hardware Transactional Memory (HTM), Software Transactional Memory (STM)

35. What is Peterson's Algorithm?

Peterson's Algorithm is a classic software-based solution to the critical section problem for exactly two processes, requiring no special hardware instructions.

Shared variables:

boolean flag[2]  // flag[i] = true: process i wants to enter
int turn         // turn = i: it's process i's turn

Algorithm (Process i, where j = 1 − i):

flag[i] = true;           // declare intent
turn = j;                 // give other process priority
while (flag[j] && turn == j) { /* busy wait */ }

// --- Critical Section ---

flag[i] = false;          // done

Properties: Satisfies Mutual Exclusion, Progress, and Bounded Waiting (bound = 1).

Limitations:

  • Only works for 2 processes
  • Uses busy-waiting (wastes CPU)
  • May not work on modern CPUs with out-of-order execution without memory barriers

36. Define Bounded Waiting

Bounded waiting is one of the three requirements for a correct critical section solution. It states:

"There must exist a finite bound on how many times other processes can enter the critical section after a process has requested entry and before that request is granted."

This prevents starvation — every process that requests entry must be guaranteed to enter within a predictable number of turns.

Without bounded waiting: Process A requests entry; B and C keep alternating indefinitely → A waits forever (violated).

With bounded waiting (Peterson's): Once Process i sets flag[i] = true, Process j can enter at most once before Process i is guaranteed to enter. Bound = 1.


37. Solutions to the Critical Section Problem

1. Software Solutions

  • Peterson's Algorithm — 2 processes, uses flag[] and turn; satisfies all 3 properties but busy-waits
  • Dekker's Algorithm — oldest correct software solution for 2 processes
  • Bakery Algorithm — generalizes to N processes; each takes a number and waits for its turn

2. Hardware Solutions

  • Disable Interrupts — works on single-processor only; not scalable
  • Test-and-Set (TSL) — atomic read + set in one uninterruptible instruction; builds spinlocks
  • Compare-and-Swap (CAS) — atomically compare and conditionally replace; foundation of lock-free programming

3. OS-Level Solutions

  • Mutex Locksacquire()/release(); blocks (sleeps) when unavailable; no busy-wait
  • Semaphores — binary (mutex) or counting (resource pool); wait()/signal()
  • Monitors — high-level language construct (Java synchronized); only one thread executes inside at a time

38. What is Banker's Algorithm?

The Banker's Algorithm is a deadlock avoidance algorithm by Edsger Dijkstra. It only grants resource requests if the resulting system state is safe — meaning a safe execution sequence for all processes still exists.

Key concepts:

  • Safe State — exists a safe sequence where every process can obtain needed resources and complete
  • Unsafe State — no such sequence exists; may lead to deadlock

Data structures (n processes, m resource types):

  • Available[m] — free instances per resource type
  • Max[n][m] — max demand of each process
  • Allocation[n][m] — currently allocated resources
  • Need[n][m] = Max − Allocation

Safety Algorithm: Simulate process completions — if all processes can finish, state is safe.

Resource Request Algorithm: Tentatively grant request → run safety check → if safe, grant; else rollback and wait.

Limitations: Requires advance declaration of max needs; assumes fixed process/resource counts; computationally expensive.


39. What is Concurrency?

Concurrency is the ability of a system to manage multiple tasks in progress at the same time through interleaving. Tasks overlap in time but don't need to execute at the exact same instant.

AspectConcurrencyParallelism
DefinitionMultiple tasks in progress at onceMultiple tasks executing at the exact same instant
RequiresSingle or multiple CPUsMultiple CPU cores
MechanismTime-sharing, interleavingTrue simultaneous execution
ExampleOne CPU switching between tasksMulti-core CPU running tasks on separate cores

Forms in OS: Multiprogramming, Multitasking, Multithreading, Distributed Computing.

Why it matters: Better CPU utilization, improved responsiveness, handles thousands of simultaneous connections (servers), enables modular software design.


40. Drawbacks of Concurrency

1. Race Conditions — shared data accessed without synchronization produces non-deterministic, incorrect results.

2. Deadlocks — circular waiting among processes; none can proceed; system effectively freezes.

3. Livelock — processes keep changing state in response to each other but make no actual progress.

4. Starvation — a process is perpetually denied CPU due to scheduling bias toward others.

5. Priority Inversion — a low-priority task holds a lock needed by a high-priority task (famously seen in NASA's Mars Pathfinder).

6. Synchronization Overhead — lock contention causes threads to spend more time waiting than doing useful work.

7. Debugging Complexity — concurrency bugs (race conditions, deadlocks) are non-reproducible and extremely difficult to trace.

8. Context Switch Overhead — frequent switches consume CPU cycles on overhead rather than useful computation.


41. Conditions Leading to Deadlock (Coffman Conditions)

Deadlock requires all four conditions to hold simultaneously:

1. Mutual Exclusion — at least one resource is held in non-shareable mode (e.g., printer, database lock).

2. Hold and Wait — a process holds at least one resource while waiting to acquire more that are held by others.

3. No Preemption — resources cannot be forcibly taken from a process; released only voluntarily.

4. Circular Wait — a circular chain exists: P0 waits for P1's resource, P1 waits for P2's, ..., Pn waits for P0's.

Key insight: Eliminating even one of these four conditions is sufficient to prevent deadlock — this is the basis of all deadlock prevention strategies.


Race Conditions — unpredictable results from unsynchronized shared data access.

Deadlocks — circular resource waiting; none can proceed.

Livelock — processes keep responding to each other without making progress.

Starvation — process perpetually bypassed by scheduler.

Priority Inversion — low-priority task blocks high-priority task holding a lock.

Memory Visibility Issues — on multicore systems, cache coherence means changes by one core may not be visible to another without memory barriers.

Atomicity Violations — operations that should be indivisible are interrupted (e.g., i++ is read-modify-write; not atomic).

Order Violations — compiler/CPU reorders instructions for optimization; memory barriers required.

Non-Determinism — concurrent programs can behave differently on each run.

Synchronization Overhead — excessive locking serializes execution, defeating concurrency benefits.


43. Why Use Precedence Graphs?

A precedence graph is a Directed Acyclic Graph (DAG) representing execution order constraints among tasks. An edge A → B means A must complete before B can start.

Why they are used:

1. Express Dependencies — makes data dependencies and logical ordering explicit and unambiguous.

2. Identify Parallelism — tasks with no path between them can run in parallel; the graph visually reveals maximum concurrency.

3. Detect Deadlocks — cycles in resource allocation graphs (a form of precedence graph) indicate circular waiting = deadlock.

4. Scheduling Optimization — OS and compilers use them to find the optimal parallel schedule minimizing total execution time.

5. Concurrency Control — in databases, enforce serializable execution order.

6. Correctness Verification — formally verify that all required orderings are maintained.


44. Explain the Resource Allocation Graph (RAG)

A Resource Allocation Graph is a directed graph representing the current state of resource allocation and requests in a system — used for deadlock detection.

Nodes:

  • Circles — Processes (P1, P2, P3...)
  • Rectangles — Resources (R1, R2...); dots inside = individual instances

Edges:

  • P → R (Request Edge) — process is waiting for that resource
  • R → P (Assignment Edge) — resource instance is allocated to that process

Deadlock Detection:

  • Single-instance resources — a cycle in the graph = deadlock
  • Multi-instance resources — cycle is necessary but not sufficient; further analysis required

Example: P1 holds R1 and requests R2; P2 holds R2 and requests R1 → cycle P1→R2→P2→R1→P1 = deadlock.

Claim edges (dashed) represent future possible requests and enable proactive avoidance (used with Banker's Algorithm).


45. What is a Deadlock?

A deadlock is a state where a set of processes are permanently blocked — each waiting for a resource held by another in the set — and none can ever proceed without external intervention.

Classic example: Process A holds a DB lock and waits for a file lock. Process B holds the file lock and waits for the DB lock. Neither can proceed.

Handling Strategies:

1. Prevention — eliminate one Coffman condition by design (e.g., require all resources requested at once to eliminate Hold and Wait).

2. Avoidance — use Banker's Algorithm to dynamically check each request keeps system in safe state.

3. Detection + Recovery — allow deadlocks; run detection algorithm periodically; recover by terminating processes or preempting resources.

4. Ignorance (Ostrich Algorithm) — assume deadlocks are rare; ignore them. Used by most general-purpose OSes (Windows, Linux).


46. Goal and Functionality of Memory Management

Goals:

  • Maximize memory utilization — minimize fragmentation
  • Enable multiprogramming — multiple processes in memory simultaneously
  • Process isolation — processes cannot access each other's memory
  • Transparency — each process sees a large, contiguous virtual address space
  • Support large address spaces — programs larger than physical RAM can run

Functions:

  • Address Translation — MMU converts logical addresses to physical addresses
  • Memory Allocation — first-fit, best-fit, worst-fit for contiguous; paging/segmentation for non-contiguous
  • Memory Deallocation — reclaims memory from terminated processes
  • Swapping/Virtual Memory — moves pages between RAM and disk
  • Fragmentation Management — uses compaction, paging, or segmentation

47. Physical Address vs. Logical Address

Logical Address (Virtual Address) — generated by the CPU during program execution. The program uses these addresses; it never sees physical addresses. Starts from 0 for each process.

Physical Address — the actual location in RAM. Used by memory hardware. Determined by the OS and MMU, not the program.

Translation: MMU hardware maps logical → physical using page tables or segment tables. Physical Address = Base Register + Logical Address (in simple base-register relocation)

FeatureLogical AddressPhysical Address
Generated byCPU during executionMMU translation
Visible toUser programMemory hardware
Range0 to (max logical space − 1)0 to (RAM size − 1)
UniquenessUnique within one processUnique system-wide
Also calledVirtual addressReal address

48. Explain Address Binding

Address binding maps a program's symbolic names (variables, labels) to actual memory addresses. This happens at different stages as a program moves from source code to execution.

Stage 1 — Compile Time: Compiler translates names to relocatable addresses. If the final memory location is known at compile time, absolute addresses can be generated (rare in modern systems).

Stage 2 — Load Time: The loader assigns actual memory addresses when the program is loaded into RAM. Once loaded, addresses are fixed for the entire execution.

Stage 3 — Execution Time (Dynamic Binding): Address binding is deferred to runtime; the MMU translates addresses dynamically. The process can be moved in memory during execution. Requires hardware support (base/limit registers, page tables). Used by all modern operating systems.


49. Types of Address Binding

1. Static (Compile-Time) Binding — absolute addresses generated at compile time; inflexible; program must load at a specific address. Used in some embedded firmware.

2. Load-Time Binding — compiler generates relocatable code; loader assigns addresses at load time; program cannot move once loaded. Used in simple systems without virtual memory.

3. Execution-Time (Dynamic) Binding — MMU translates addresses at runtime; process can be relocated during execution; requires hardware support (base+limit registers, page tables). Used by all modern OSes.

4. Dynamic Linking — library code linked at first runtime call, not at compile time; multiple processes share one copy in memory. Examples: .dll (Windows), .so (Linux).


50. Advantage of Dynamic Allocation Algorithms

Dynamic memory allocation (first-fit, best-fit, worst-fit, buddy system) offers these advantages over static allocation:

  • Efficient utilization — memory allocated only when needed, freed when done
  • Handles variable-size processes — no fixed partition sizes required
  • Supports memory growth — processes can request more memory at runtime (malloc)
  • Higher multiprogramming — more processes fit in memory overall
  • No advance knowledge needed — works even when a program's memory needs are unknown until runtime
  • Immediate reclamation — memory freed instantly when a process exits, available for others

51. Define Compaction

Compaction is a memory management technique that eliminates external fragmentation by physically moving all allocated memory blocks together so all free holes merge into one large contiguous block.

How it works:

  1. OS identifies all allocated blocks and free holes
  2. Copies all process data to new adjacent locations (packing them together)
  3. All free space consolidates at one end of memory
  4. Address references in relocated processes are updated

Requirements: Execution-time (dynamic) address binding must be in use — otherwise process addresses cannot be updated.

Cost: Very expensive — copying large amounts of memory takes significant time (O(n) in data size).

Modern alternative: Paging avoids external fragmentation entirely without needing compaction, making it the preferred approach in modern virtual memory systems.


52. Hashed-Page Table: Advantages & Disadvantages

A hashed-page table uses a hash function to map virtual page numbers to page table entries. Each hash bucket contains a linked list of entries: (virtual page#, physical frame#, next pointer).

Advantages:

  • Space-efficient — only entries for allocated pages exist (ideal for large, sparse address spaces)
  • O(1) average lookup — fast with a good hash function and low collision rate
  • Scales to 64-bit spaces — flat page tables would be impractically large
  • Supports clustered tables — multiple mappings per bucket; efficient for spatial locality

Disadvantages:

  • Collision overhead — linked list traversal on collisions; O(n) worst case
  • Extra memory per entry — needs virtual page# for collision verification + next pointer
  • Cache-unfriendly — pointer chasing causes cache/TLB misses
  • Complex implementation — requires careful hash function design

53. Paging vs. Segmentation

Paging — physical memory divided into fixed-size frames; logical address space divided into equal-size pages; pages mapped to frames via page table.

Segmentation — logical address space divided into variable-size segments based on program structure (code, data, stack, heap); each segment has a base and limit.

FeaturePagingSegmentation
Division basisFixed-size (physical)Variable-size (logical)
External FragmentationNoneYes
Internal FragmentationYes (last page)None
Address format(page#, offset)(segment#, offset)
Programmer visibilityInvisibleVisible
SharingHarderEasier (whole segments)
ProtectionAt page levelAt segment level

Combined approach: Many architectures (Intel x86, MULTICS) use both — segments divided internally into pages. Modern x86-64 uses primarily paging with segmentation as a legacy feature.


54. Associative Memory & Cache Memory

Associative Memory (Content-Addressable Memory — CAM) is searched by content value, not by address. All entries are compared simultaneously in parallel — O(1) lookup regardless of size. Much more expensive than regular RAM. Primary OS use: TLB — finds virtual-to-physical page mapping in one parallel lookup cycle.

Cache Memory is a small, fast memory between the CPU and RAM. Stores copies of frequently accessed data to reduce average memory access time.

  • Physically on or near the CPU chip
  • Organized in levels: L1 (fastest, ~32–64 KB per core), L2 (~256 KB–1 MB), L3 (~4–64 MB shared)
  • Transparent to programmers — hardware manages it automatically
  • On a cache hit, data returned in sub-nanoseconds. On a cache miss, data fetched from RAM and stored in cache.

55. What is Locality of Reference?

Locality of reference (principle of locality) is the observation that programs tend to access a small, consistent portion of their address space at any given time.

Temporal Locality — if a memory location is accessed at time T, it is likely to be accessed again soon. Reason: loops re-execute the same instructions; variables are read/written repeatedly.

  • Example: loop variable i and accumulator sum are accessed on every iteration.

Spatial Locality — if a location is accessed, nearby locations are likely to be accessed soon. Reason: sequential code execution, array traversal, related data stored together.

  • Example: accessing a[5] makes access to a[6], a[7] likely.

Why it matters:

  • CPU caches exploit both types — cache lines (64 bytes) loaded at once for spatial locality
  • Virtual memory works because the working set (actively used pages) is small at any time
  • Hardware prefetchers predict and preload data before it's needed

56. Advantages of Virtual Memory

Virtual memory lets processes use more address space than available physical RAM, using secondary storage as an extension.

  • Run programs larger than RAM — only active pages need to be in physical memory
  • Higher multiprogramming — more processes fit in memory since each needs only its active pages in RAM
  • Process isolation — each process has its own virtual address space starting from 0; MMU enforces boundaries
  • Simplified memory allocation — process sees large contiguous space; OS handles fragmented physical layout
  • Memory sharing — shared libraries (libc, system DLLs) mapped into multiple processes from one physical copy
  • Efficient use — unaccessed pages (error handlers, rarely used features) never occupy RAM
  • Copy-on-Write (COW) — forked processes share pages; private copy made only when one writes → saves memory and time

57. Calculating Performance in Virtual Memory

Performance depends on the page fault rate — every page fault triggers expensive disk I/O.

Effective Access Time (EAT) Formula:

EAT = (1 − p) × ma + p × page_fault_time

Where p = page fault probability, ma = memory access time, page_fault_time = time to service a fault (disk I/O dominated).

Example Calculation:

  • ma = 200 ns, page_fault_time = 8,000,000 ns (8 ms HDD), p = 0.001
EAT = 0.999 × 200 + 0.001 × 8,000,000
    = 199.8 + 8,000 = 8,199.8 ns   (~40× slower than pure RAM)

Key factors affecting performance: Page replacement algorithm (LRU >> FIFO), RAM size vs. working set size, page size, disk speed (SSD vs. HDD), TLB hit rate.

Thrashing — extremely high page fault rate where system spends more time swapping than executing. Fix: add RAM, reduce multiprogramming degree, use working set model.


58. Basic Concept of the File System

A file system organizes, stores, retrieves, and manages data on storage devices, providing the abstraction of files (named data collections) and directories (organizational containers).

File System Structure:

  • Boot Block — bootstrap code to load the OS
  • Superblock — metadata about the entire file system (total blocks, free blocks, block size)
  • Inode Table — stores file metadata (size, permissions, timestamps, block pointers)
  • Data Blocks — actual file contents

File Allocation Methods:

  • Contiguous — file occupies consecutive blocks; fast sequential access; suffers external fragmentation
  • Linked — blocks linked by pointers; no fragmentation; slow random access
  • Indexed — an index block holds all pointers; used by Unix inodes; efficient for both sequential and random access

Examples: ext4, NTFS, FAT32, exFAT, APFS, ZFS, Btrfs, XFS.


59. Operations on a File

Create — allocate space, assign inode, set metadata, register in directory.

Open — load metadata into memory, check permissions, return file descriptor, set file pointer to position 0.

Read — copy data from current file pointer position into user buffer; advance pointer.

Write — copy data from user buffer into file at current position; extend file if needed; advance pointer.

Seek — move file pointer to specified position without reading/writing (enables random access).

Close — flush buffered writes, release file descriptor, free kernel resources.

Delete (Unlink) — remove directory entry; free disk blocks when link count reaches 0 and no process has it open.

Truncate — reduce file to zero (or specified) length while preserving metadata.

Rename/Move — change file name or move to different directory.

Get/Set Attributes — read or modify permissions (chmod), ownership (chown), timestamps.

Lock — establish advisory or mandatory locks for concurrent access coordination.

Memory Map (mmap) — map file contents directly into process's virtual address space.


60. Define the Term Bit-Vector

A bit-vector (bitmap) is a data structure for free space management on a storage device. Each bit represents one disk block: 1 = free, 0 = allocated (or vice versa, by convention).

Structure example:

Block:  0  1  2  3  4  5  6  7
Bit:    1  1  0  0  1  0  1  1
       free free used used free used free free

Operations:

  • Find free block — scan for first 1 bit (hardware bit-scan is very fast)
  • Allocate — set bit to 0
  • Free — set bit to 1

Advantages: Simple, compact, hardware-accelerated scanning, naturally supports contiguous allocation (find a run of 1 bits).

Disadvantages: For very large disks, the bitmap itself can be large; not efficient for networked file systems.

Used in: ext2/3/4 (Linux), NTFS, HFS+.


61. What is a File Allocation Table?

FAT (File Allocation Table) is both a file system type and the core data structure within it — an array where each entry corresponds to one cluster and stores the next cluster in a file's chain.

Entry values:

  • 0x0000 — cluster is free
  • 0xFFF7 — bad cluster
  • 0xFFFF / 0x0FFFFFFF — end-of-file marker
  • Any other value — index of next cluster in the chain

How files are stored: A directory entry holds the file name, size, and starting cluster. To read the file, follow the FAT chain: start → FAT[start] → FAT[FAT[start]] → ... → end-of-chain.

VariantMax VolumeMax File Size
FAT162 GB2 GB
FAT322 TB4 GB
exFAT128 PB16 EB

Limitations: No file permissions, no journaling (prone to corruption), FAT32 max 4 GB/file (problematic for modern video files).


62. What is Rotational Latency?

Rotational latency is the time for the desired disk sector to rotate under the read/write head after the arm has been positioned on the correct track (after seek completes).

Formula:

Average Rotational Latency = 60 / (2 × RPM) seconds

Examples:

  • 7200 RPM drive: 60 / (2 × 7200) = 4.17 ms
  • 15000 RPM drive: 60 / (2 × 15000) = 2 ms

Total Disk Access Time:

Total = Seek Time + Rotational Latency + Transfer Time

SSDs have zero rotational latency — no spinning disk, no physical rotation required. This is a primary reason SSDs are dramatically faster for random I/O than HDDs.


63. What is Seek Time?

Seek time is the time for the disk arm to physically move the read/write head from its current position to the track containing the desired data.

Types:

  • Average seek time: ~4–9 ms (consumer 7200 RPM HDDs) — most commonly cited
  • Full stroke seek time: ~15–20 ms — head moves from outermost to innermost track
  • Track-to-track seek time: ~0.3–1 ms — head moves one track

Since seek time dominates random I/O performance, disk scheduling algorithms exist to minimize it:

  • FCFS — process in arrival order; simple but poor performance
  • SSTF (Shortest Seek Time First) — always service closest request; good performance but can starve distant requests
  • SCAN (Elevator) — head sweeps back and forth; fair, no starvation
  • C-SCAN (Circular SCAN) — head sweeps one way only, jumps back; more uniform wait times

64. What is Belady's Anomaly?

Belady's Anomaly is the counterintuitive observation that in the FIFO page replacement algorithm, allocating more physical memory frames can increase the number of page faults.

Discovered by László Bélády in 1969.

Classic example (Reference string: 1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5):

  • With 3 frames (FIFO) → 9 page faults
  • With 4 frames (FIFO) → 10 page faults (MORE with more memory!)

Why it happens: FIFO evicts the oldest page, not the least useful one. With more frames, a different (sometimes worse) set of pages is retained, causing more faults on certain access patterns.

Algorithms immune to Belady's Anomaly (those with the stack property):

  • OPT (Optimal Replacement)
  • LRU (Least Recently Used)

FIFO lacks the stack property, making it vulnerable to this anomaly.


65. Non-Recursive Mutex Locked More Than Once

A non-recursive (non-reentrant) mutex does not allow the same thread to lock it again without first releasing it.

What happens: The thread deadlocks itself — it blocks waiting for the mutex to be released, but it's the only thread that can release it, and it's blocked. The thread waits forever.

On POSIX systems: Behavior is officially undefined, but in practice:

  • The thread deadlocks (most common)
  • Returns EDEADLK error (with error-checking mutex type enabled)

Contrast — Recursive Mutex: Tracks the owning thread and a lock count. Same thread can lock() multiple times; each lock() increments count; unlock() decrements it. Only when count reaches 0 is it released. No self-deadlock possible.

Why non-recursive mutexes exist: Simpler and faster (no ownership tracking); double-locking usually indicates a design flaw — making it error is actually useful for catching bugs early.


66. Advantages of a Multiprocessor System

1. Increased Throughput — processes/threads execute in true parallel; compute-intensive tasks (ML, video encoding, simulations) complete faster.

2. Economy of Scale — shared peripherals, storage, power, and networking reduce cost vs. equivalent separate systems.

3. Fault Tolerance — if one CPU fails, others continue running (graceful degradation); critical for banking, hospitals, air traffic control.

4. Load Balancing — OS scheduler dynamically distributes threads to underutilized processors.

5. Support for Real-Time Applications — dedicated CPUs can handle real-time tasks while others manage general workloads.

6. Scalability — add more CPUs to increase power without replacing the whole system.

7. True Parallelism for Multithreaded Apps — web servers, databases, and ML frameworks are heavily multithreaded; multiprocessors eliminate the bottleneck of simulated concurrency.


67. What are Real-Time Systems?

Real-time systems are computing systems where the correctness of results depends on both logical accuracy AND the time the result is produced. A correct result delivered too late is as bad as a wrong result.

Classification:

  • Hard Real-Time — missing a deadline is catastrophic. Examples: aircraft flight control, pacemakers, ABS brakes, nuclear reactors. Requires formal timing verification.
  • Soft Real-Time — missing a deadline degrades quality but doesn't cause failure. Examples: video streaming, online gaming, multimedia.
  • Firm Real-Time — missed deadline renders result useless, but system continues. Examples: sensor data processing.

Characteristics:

  • Deterministic — execution times bounded and predictable
  • Priority-based preemptive scheduling — highest priority task always preempts lower ones
  • Minimal interrupt latency — interrupts serviced within guaranteed time bounds
  • No or controlled virtual memory — page faults introduce unpredictable delays
  • Priority Inheritance/Ceiling Protocol — prevents priority inversion

68. How to Recover from a Deadlock?

Once a deadlock is detected, the OS must break it using one of two strategies:

Strategy 1: Process Termination

  • Option A — Kill all deadlocked processes: Simple but all work done by those processes is lost.
  • Option B — Kill one at a time: Run detection after each kill until deadlock is broken. Less wasteful but more overhead.

Victim Selection Criteria: Minimum priority, least CPU time used, fewest resources held, easiest to restart, batch (not interactive) process.

Strategy 2: Resource Preemption

  • Forcibly take a resource from a victim process and give it to another
  • Rollback the victim to a safe checkpoint (requires checkpointing support)
  • Prevent starvation — track how many times a process has been preempted; factor into victim selection cost so the same process isn't always chosen

Most systems combine both strategies: try preemption first (less disruptive), fall back to termination if needed.


69. Factors for Using Deadlock Detection Algorithm

The decision to use detection (rather than prevention or avoidance) depends on:

1. Deadlock Frequency — if deadlocks are rare, the periodic overhead of detection is acceptable; if frequent, detection + recovery overhead becomes too expensive.

2. System Scale — detection algorithms have O(n²) or O(n × m) complexity; very large systems make frequent detection prohibitively expensive.

3. Recovery Cost vs. Avoidance Cost — if process termination/rollback is cheap (short transactions), detection is preferred; if recovery is expensive (long computations), continuous avoidance is better.

4. Ability to Declare Maximum Resource Needs — Banker's Algorithm requires each process to declare max needs upfront. In dynamic systems where this is unknown, detection is the only option.

5. Real-Time Constraints — RTOS systems require predictable latency; both detection and avoidance add overhead, so prevention (eliminating a Coffman condition by design) is preferred.

6. System Domain — general-purpose OSes use the Ostrich Algorithm; databases run detection periodically; embedded/RTOS systems use prevention.

7. Invocation Policy — detection can be triggered: after every resource request (max overhead), periodically (balanced), or when CPU utilization drops significantly (a symptom of deadlock).

Operating System — Process Management (Q70–Q89)


70. What is a Process?

A process is a program in execution — an active instance of a program that has been loaded into memory and is being executed by the CPU. A program by itself is just a passive set of instructions stored on disk; it becomes a process when the OS loads it into RAM and begins running it.

A process is more than just program code — it includes:

  • Program code (Text section) — the executable instructions
  • Program Counter — address of the next instruction to execute
  • CPU Registers — current working values (accumulators, stack pointer, etc.)
  • Process Stack — temporary data (function parameters, local variables, return addresses)
  • Heap — dynamically allocated memory (via malloc, new)
  • Data Section — global and static variables

Key characteristics:

  • Each process has its own isolated address space — it cannot access another process's memory
  • A process can create child processes (via fork() in Unix)
  • Processes communicate via IPC mechanisms (pipes, shared memory, sockets)
  • The OS tracks every process through a Process Control Block (PCB)

Process vs. Program:

AspectProgramProcess
NaturePassive (file on disk)Active (executing in memory)
ExistencePermanent until deletedTemporary (created and terminated)
ResourcesNoneCPU, memory, files, I/O
InstancesOne program can have multiple processesEach process is unique

71. What is a Process and Process Table?

Process

A process is a program in execution. It is the fundamental unit of work in an operating system. Each process runs in its own address space and is independently scheduled by the OS. (See Q70 for full details.)

Process Table

The process table (also called the process list) is a data structure maintained by the OS that contains one entry for every process currently in the system. Each entry is a Process Control Block (PCB) — a record holding all information the OS needs to manage that process.

What the process table contains (one row per process):

  • Process ID (PID)
  • Process state (new, ready, running, waiting, terminated)
  • CPU registers and Program Counter
  • Memory allocation info (base address, page table pointer)
  • Scheduling information (priority, CPU time used)
  • I/O status (open file descriptors, I/O devices in use)
  • Accounting info (CPU time, start time)

Why it's important:

  • The OS references the process table on every context switch to save and restore process state
  • The scheduler scans the process table to find the next process to run
  • Process creation adds an entry; process termination removes it
  • On Linux, the process table is implemented as a circular doubly-linked list of task_struct structures

Process Table Size: Finite — the OS can only track a fixed number of processes simultaneously. When full, no new processes can be created (zombie processes filling the table is a real concern).


72. Different States of a Process

A process transitions through several states during its lifetime. The number of states varies by OS design, but the standard model defines five states:

1. New

The process has just been created but has not yet been admitted to the pool of executable processes. The OS is in the process of allocating resources (memory, PCB entry) and loading the program.

2. Ready

The process is loaded in memory, has all resources it needs, and is waiting for CPU time. It is in the ready queue, waiting for the scheduler to select it.

3. Running

The process is currently executing on the CPU — its instructions are being processed. On a single-core CPU, only one process can be in this state at a time.

4. Waiting (Blocked)

The process cannot continue until some event occurs — typically completion of an I/O operation (waiting for disk read, network packet, keyboard input). It is removed from the ready queue and placed in a wait queue.

5. Terminated (Exit)

The process has finished execution or been killed. The OS is in the process of reclaiming its resources (memory, file descriptors). The PCB entry remains briefly until the parent calls wait().

State Transition Diagram:

                  admitted
  New ─────────────────────────► Ready
                                  │  ▲
              scheduler dispatch  │  │ interrupt / preemption
                                  ▼  │
                              Running ──────────────► Terminated
                                  │                   (exit/kill)
                     I/O or event │
                         request  │
                                  ▼
                              Waiting
                                  │
                     I/O or event │ completion
                                  ▼
                               Ready

State Transitions:

  • New → Ready: OS admits process (resources allocated)
  • Ready → Running: Scheduler dispatches the process
  • Running → Ready: Preempted by OS (time quantum expired)
  • Running → Waiting: Process requests I/O or waits for event
  • Waiting → Ready: I/O completes or event occurs
  • Running → Terminated: Process calls exit() or is killed

73. Explain the States of a Process

The five process states represent the lifecycle of a process from creation to termination:

New State

A process enters the New state when it is first created (via fork() or process creation system call). The OS allocates a PCB, assigns a PID, and sets up the initial memory layout. The process is not yet eligible for CPU scheduling.

Ready State

Once the OS has finished initialization and allocated necessary resources, the process moves to Ready. It sits in the ready queue — a data structure holding all processes that are loaded in memory and waiting for CPU time. Multiple processes can be in this state simultaneously.

Running State

The scheduler picks a process from the ready queue and the dispatcher gives it the CPU. The process is now Running — its instructions are executing. It can leave this state in three ways:

  • Preemption → back to Ready (time quantum expired or higher-priority process arrives)
  • I/O request → move to Waiting
  • Completion/error → move to Terminated

Waiting (Blocked) State

When a running process needs to wait for a resource or event (disk I/O, network data, user input, semaphore signal), it cannot usefully execute. It moves to the Waiting state and is placed in an I/O wait queue. The CPU is freed for other processes. When the event completes (interrupt from disk, network, timer), the process moves back to Ready.

Terminated State

When a process calls exit(), completes its last instruction, or is killed by the OS or another process (via kill()), it enters the Terminated state. Resources (memory, file handles) are released. The PCB is kept briefly as a zombie until the parent reads the exit status via wait().

Additional states in some OS models:

  • Suspended Ready — process moved to secondary storage (swapped out) but ready to run when brought back
  • Suspended Waiting — swapped out and waiting for an event

74. What is a Process Control Block (PCB)?

A Process Control Block (PCB) is a data structure maintained by the OS that contains all the information needed to manage a specific process. It is the OS's complete representation of a process — if the PCB is lost, the process is effectively lost.

Each process has exactly one PCB, created when the process is created and deleted when the process terminates.

Information Stored in a PCB

1. Process Identification

  • PID (Process ID) — unique integer identifier for the process
  • Parent PID — PID of the process that created this one
  • User ID — which user owns the process

2. Process State

  • Current state: New, Ready, Running, Waiting, or Terminated

3. CPU Registers & Program Counter

  • Contents of all CPU registers at the last context switch
  • Program Counter (PC) — address of next instruction to execute
  • Stack pointer, base/limit registers, condition codes

4. CPU Scheduling Information

  • Process priority
  • Scheduling queue pointers
  • CPU time used (for accounting and scheduling decisions)

5. Memory Management Information

  • Base and limit registers (simple allocation) or page table pointer (virtual memory)
  • Size of code, data, and stack segments

6. I/O Status Information

  • List of I/O devices allocated to the process
  • List of open files (file descriptor table)
  • Pending I/O requests

7. Accounting Information

  • Total CPU time used
  • Time since process creation (wall clock time)
  • Time limits, job/account numbers

Role of PCB in Context Switching

When the OS switches from Process A to Process B:

  1. Save all CPU registers and PC into Process A's PCB
  2. Load all CPU registers and PC from Process B's PCB
  3. CPU continues executing Process B from exactly where it left off

On Linux, the PCB is the task_struct — a large C structure in the kernel containing over 100 fields.


75. What is Context Switching?

Context switching is the process of saving the state of a currently running process and restoring the state of a previously paused process so that the CPU can switch between processes without losing progress.

It is the fundamental mechanism that enables multitasking — making multiple processes share a single CPU.

Steps in a Context Switch

  1. Trigger — a timer interrupt (preemption), I/O request, or system call causes the OS to invoke the scheduler
  2. Save current context — the OS saves the running process's CPU registers, program counter, stack pointer, and other state into its PCB
  3. Update PCB — the current process's state is updated (e.g., Running → Ready or Running → Waiting)
  4. Select next process — the scheduler picks the next process to run from the ready queue
  5. Restore new context — the OS loads the selected process's saved state from its PCB into the CPU registers
  6. Resume execution — the CPU continues the new process from exactly where it previously stopped

Context Switch Overhead

During a context switch, the CPU does no useful work — it only manages OS bookkeeping. This is pure overhead.

Additional costs:

  • TLB flush — virtual address mappings for the old process are invalidated; new ones must be loaded
  • Cache cold start — the new process's data is not in cache yet; early cache misses slow execution

Typical context switch time: 1–10 microseconds on modern hardware.

Minimizing Context Switch Cost

  • Use hardware-assisted context switch mechanisms (e.g., x86 TSS, though rarely used)
  • Use threads instead of processes (thread switches are cheaper — same address space, no TLB flush)
  • Use green threads / coroutines (user-space scheduling with minimal kernel involvement)
AspectProcess Context SwitchThread Context Switch
Address spaceChanges (full TLB flush)Same (no TLB flush)
CostHigherLower
State savedFull CPU + memory contextCPU registers only

76. Difference Between a Process and a Thread

A process is an independent program in execution with its own address space, resources, and OS-managed state.

A thread is a unit of execution within a process — a "lightweight process." Multiple threads within the same process share the process's resources but execute independently.

Key Differences

FeatureProcessThread
DefinitionIndependent program in executionUnit of execution within a process
Address SpaceOwn private address spaceShares address space with other threads in same process
ResourcesOwn copy of code, data, heap, stack, filesShares code, data, heap, files; own stack and registers only
Creation OverheadHigh (new address space, PCB, resource allocation)Low (just a new stack + registers within existing process)
Context SwitchExpensive (TLB flush, full state save)Cheaper (no TLB flush, same address space)
CommunicationIPC (pipes, shared memory, sockets) — complexDirect read/write of shared memory — simple but needs sync
IsolationCrash in one process doesn't affect othersCrash in one thread can kill the entire process
IndependenceFully independentDependent — shares fate with the process
Creation System Callfork()

(Unix)

pthread_create()

(POSIX), CreateThread(){' '} (Windows)

ExampleTwo separate browsers runningMultiple tabs in the same browser

When to Use Processes vs. Threads

Use processes when:

  • Tasks need strong isolation (security, stability)
  • Tasks run different programs entirely

Use threads when:

  • Tasks share data and need fast communication
  • Tasks are logically part of the same job
  • Performance matters (less overhead)

77. What is a Thread?

A thread (or thread of execution) is the smallest unit of CPU execution within a process. A process can contain one or more threads, all sharing the process's code, data, heap, and open files, but each having its own:

  • Program Counter — tracks which instruction the thread is executing
  • CPU Registers — current working values
  • Stack — local variables, function call history

Threads are sometimes called lightweight processes because creating a thread is much cheaper than creating a full process.

Types of Threads

1. User-Level Threads (ULT) Managed entirely in user space by a thread library (no kernel involvement). The kernel sees only one process — it is unaware of individual threads. Very fast to create and switch. Drawback: if one thread blocks on I/O, the entire process blocks (kernel blocks the whole process).

2. Kernel-Level Threads (KLT) Managed directly by the OS kernel. The kernel knows about each thread and schedules them independently. If one thread blocks, others in the same process continue. More overhead per thread but better parallelism and I/O handling. Examples: Linux pthreads, Windows threads.

3. Hybrid Threads Maps multiple user-level threads to multiple kernel-level threads. Balances flexibility and performance. Used in Solaris and some modern systems.

Thread Models

  • 1:1 (One-to-One) — each user thread maps to one kernel thread (Linux, Windows)
  • N:1 (Many-to-One) — all user threads map to one kernel thread (green threads)
  • M:N (Many-to-Many) — M user threads mapped to N kernel threads (Solaris)

78. Differences Between Process and Thread

(Detailed comparison — see also Q76 for the summary table)

Address Space

  • Process — each process has a completely separate virtual address space. Memory of one process is invisible to another.
  • Thread — all threads within the same process share the same address space. Any thread can access any shared variable.

Resource Ownership

  • Process — owns its code segment, data segment, heap, stack, and all open file descriptors independently.
  • Thread — owns only its own stack and register set. Everything else (code, data, heap, files) is shared with other threads in the process.

Creation and Termination

  • Process — creation via fork() is expensive. OS must allocate a new address space, copy parent's page table, create new PCB.
  • Thread — creation via pthread_create() is cheap. OS only allocates a new stack and registers within the existing process.

Communication

  • Process — must use IPC mechanisms (pipes, message queues, sockets, shared memory) — explicit and managed by the OS.
  • Thread — communicates directly through shared memory — simple and fast, but requires synchronization (mutexes, semaphores) to prevent race conditions.

Fault Isolation

  • Process — a crash (segfault, unhandled exception) affects only that process. Other processes continue safely.
  • Thread — a crash in one thread (e.g., NULL pointer dereference) typically kills all threads in the process.

Scheduling

  • Process — scheduled by the OS based on process-level priority and state.
  • Thread — each kernel thread is independently scheduled by the OS. On multicore systems, threads in the same process can run truly in parallel.

79. Benefits of Multithreaded Programming

Multithreaded programming involves a process creating multiple threads that run concurrently. It offers significant advantages:

1. Responsiveness In a multithreaded application, one thread can handle user interface interactions while another performs heavy computation or I/O in the background. The app remains responsive even during long operations. Example: a web browser loads a page on one thread while another thread responds to user scrolling.

2. Resource Sharing Threads naturally share the process's code, data, and files. No IPC overhead needed for communication between threads in the same process — they simply read/write shared variables.

3. Economy (Efficiency) Creating a thread is far cheaper than creating a new process — it requires only a new stack and register set. Context switching between threads is also faster (no TLB flush, same address space).

4. Scalability / Parallelism On multicore/multiprocessor systems, different threads run simultaneously on different cores, achieving true parallel execution. A single-threaded program can only use one core, regardless of how many are available.

5. Better Server Performance Web servers, database servers, and game servers create one thread per client connection. Thousands of concurrent client requests are handled in parallel rather than sequentially.

6. Simplified Program Structure Programs with multiple independent tasks (e.g., reader + processor + writer pipeline) are naturally expressed as multiple threads, improving code clarity and modularity.

7. Faster Context Switching Switching between threads within the same process is significantly cheaper than switching between processes — same address space means no TLB invalidation and better cache utilization.


80. What is Multithreading?

Multithreading is the ability of a CPU or an OS to execute multiple threads of a single process concurrently. It allows a program to perform multiple tasks simultaneously within the same process, sharing the process's resources.

Why Multithreading Exists

A single-threaded process can only do one thing at a time. If it waits for I/O, the CPU is idle. Multithreading keeps the CPU busy by running other threads while one waits.

Types of Multithreading

1. Fine-Grained Multithreading The CPU switches between threads on every clock cycle (or very frequently). Hides individual instruction latency effectively but has high switching overhead.

2. Coarse-Grained Multithreading The CPU switches threads only on long-latency events (e.g., cache miss, I/O). Less switching overhead but less effective at hiding small latencies.

3. Simultaneous Multithreading (SMT) / Hyperthreading Hardware technique where a single physical CPU core executes instructions from multiple threads simultaneously by duplicating architectural state (registers, PC) while sharing execution units and cache. Intel's Hyperthreading makes one physical core appear as two logical cores to the OS.

Multithreading Models

  • 1:1 (One-to-One) — each user thread is a kernel thread. Best parallelism; used by Linux, Windows. Overhead: creating many threads is expensive.
  • N:1 (Many-to-One) — all user threads share one kernel thread. Fast thread switching in user space, but no parallelism on multicore.
  • M:N (Many-to-Many) — M user threads mapped to N kernel threads. Flexible and efficient. Used in older Solaris, some JVM implementations.

Real-World Examples

  • Web browsers (each tab is a thread or process)
  • Web servers (one thread per request)
  • Video games (separate threads for rendering, physics, audio, networking)
  • IDEs (UI thread + background compilation/analysis thread)

81. Concept of Process Scheduling

Process scheduling is the activity of the OS's scheduler in deciding which process from the ready queue should be given the CPU next and for how long. It is central to achieving efficient CPU utilization and good system responsiveness.

Why Scheduling is Needed

  • Multiple processes exist simultaneously in a multiprogrammed system
  • Only one process can run on a CPU core at a time (on a single-core system)
  • Without scheduling, processes would monopolize the CPU

Scheduling Queues

The OS maintains several queues to track process states:

  • Job Queue — all processes in the system (including those on disk, not yet admitted)
  • Ready Queue — processes loaded in memory, ready to run; implemented as a linked list of PCBs
  • I/O Wait Queues — separate queue for each I/O device; processes waiting for that device

As a process moves through its lifecycle, it moves between these queues.

Scheduling Decisions

The scheduler makes decisions at four points:

  1. When a process switches from Running → Waiting (I/O request)
  2. When a process switches from Running → Ready (preemption)
  3. When a process switches from Waiting → Ready (I/O completion)
  4. When a process terminates

Decisions at points 1 and 4 are non-preemptive (only the running process can trigger them). Points 2 and 3 can be preemptive (OS can intervene).

Scheduling Criteria

CPU utilization, throughput, turnaround time, waiting time, response time, fairness.


82. Types of Schedulers

The OS uses three types of schedulers, each operating at different timescales:

Long-Term Scheduler (Job Scheduler)

  • Frequency: Runs infrequently (seconds to minutes apart)
  • Function: Selects processes from the job pool (processes waiting on disk) and loads them into main memory for execution — admits them to the ready queue
  • Controls: The degree of multiprogramming — how many processes are in memory at once
  • Aim: Maintain a good balance between I/O-bound processes (spend most time on I/O) and CPU-bound processes (spend most time on CPU)
  • Present in: Batch systems; often absent in time-sharing systems (like Linux) where all processes are admitted immediately

Short-Term Scheduler (CPU Scheduler)

  • Frequency: Runs very frequently — every milliseconds (on every timer interrupt, I/O completion, system call)
  • Function: Selects which process in the ready queue gets the CPU next and invokes the dispatcher
  • Most critical scheduler — its performance directly affects system responsiveness and CPU utilization
  • Must be extremely fast — runs hundreds of times per second; even a small overhead adds up

Medium-Term Scheduler (Swapper)

  • Frequency: Moderate — triggered when memory pressure increases
  • Function: Swaps processes out of memory to disk (swap space) when memory is overloaded, and swaps them back in when memory frees up
  • Purpose: Reduce the degree of multiprogramming temporarily to relieve memory pressure; allows a partially run process to be continued later
  • Process state: Swapped-out processes enter the Suspended state
SchedulerFrequencyOperates OnControls
Long-TermInfrequent (minutes)Job pool → MemoryDegree of multiprogramming
Short-TermVery frequent (ms)Ready queue → CPUWhich process runs next
Medium-TermModerateMemory ↔ Disk (swap)Memory pressure relief

83. Preemptive vs. Non-Preemptive Scheduling

Non-Preemptive Scheduling

Once a process is given the CPU, it keeps the CPU until it voluntarily releases it — either by completing, calling a blocking I/O operation, or explicitly yielding.

  • The OS cannot forcibly take the CPU away from a running process
  • Simpler to implement; no need for a timer interrupt
  • Risk: one long-running process can monopolize the CPU, starving others
  • Examples: FCFS, SJF (non-preemptive), early Windows (cooperative multitasking)

Preemptive Scheduling

The OS can forcibly take the CPU from a running process based on:

  • Time quantum expiry (timer interrupt)
  • Arrival of a higher-priority process

  • Ensures fairness and responsiveness
  • Requires timer hardware and careful handling of shared data (race conditions can occur if a process is interrupted mid-update)
  • Examples: Round Robin, Preemptive SJF (SRTF), Preemptive Priority Scheduling, Linux CFS
FeatureNon-PreemptivePreemptive
CPU releaseVoluntary onlyVoluntary or forced by OS
FairnessLower (long jobs monopolize)Higher
ResponsivenessLowerHigher
ImplementationSimplerMore complex
RiskCPU starvation of other processesRace conditions on shared data
ExamplesFCFS, non-preemptive SJFRound Robin, SRTF

84. Common Scheduling Algorithms

FCFS — First Come First Served

Processes are executed in the order they arrive in the ready queue. Non-preemptive.

Example: Processes P1 (24ms), P2 (3ms), P3 (3ms) arrive in order.

Gantt Chart: | P1 (0–24) | P2 (24–27) | P3 (27–30) |
Average Waiting Time = (0 + 24 + 27) / 3 = 17 ms

Drawback: Convoy effect — short processes wait behind long ones, resulting in poor average waiting time.

SJF — Shortest Job First

The process with the shortest CPU burst is scheduled next. Provides the minimum average waiting time for a given set of processes.

  • Non-Preemptive SJF: Once started, process runs to completion.
  • Preemptive SJF (SRTF — Shortest Remaining Time First): If a new process arrives with a shorter remaining time than the current process, the current process is preempted.

Drawback: Starvation of long processes if short processes keep arriving. Difficulty: CPU burst length must be estimated (usually using exponential averaging of past bursts).

Round Robin (RR)

Each process gets the CPU for a fixed time quantum (q), then is preempted and moved to the back of the ready queue. Designed for time-sharing systems.

Performance depends on time quantum size:

  • Large q → degenerates to FCFS
  • Small q → very fast switching; high context switch overhead
  • Typical q: 10–100 milliseconds

Example (q = 4ms): P1(24ms), P2(3ms), P3(3ms)

| P1(0–4) | P2(4–7) | P3(7–10) | P1(10–14) | P1(14–18) | P1(18–22) | P1(22–26) | P1(26–28) |
Average Waiting Time = (6 + 4 + 7) / 3 = 5.67 ms

Priority Scheduling

Each process is assigned a priority number. The CPU is given to the highest-priority process. Can be preemptive or non-preemptive.

  • Internal priorities set by OS based on memory usage, CPU time, I/O ratio
  • External priorities set by users or administrators
  • Drawback: Starvation — low-priority processes may never run. Solution: Aging (gradually increase priority of waiting processes).

85. What is FCFS?

FCFS (First Come First Served) is the simplest CPU scheduling algorithm. Processes are dispatched to the CPU in the order they arrive in the ready queue — the first process to arrive runs first, then the next, and so on. It is non-preemptive.

How It Works

The ready queue is managed as a simple FIFO queue. When a process arrives, it joins the back of the queue. The CPU picks from the front of the queue. The running process holds the CPU until it finishes or blocks for I/O.

Example

ProcessArrival TimeBurst Time
P1010 ms
P215 ms
P328 ms
Gantt Chart: | P1 (0–10) | P2 (10–15) | P3 (15–23) |

Waiting Time: P1 = 0, P2 = 9, P3 = 13
Average Waiting Time = (0 + 9 + 13) / 3 = 7.33 ms

Advantages

  • Extremely simple to implement and understand
  • No starvation — every process eventually gets the CPU (FIFO guarantees eventual service)
  • No overhead (no priority calculations, no preemption)

Disadvantages

  • Convoy Effect — one long CPU-bound process holds the CPU while many shorter processes wait behind it, resulting in high average waiting time
  • Poor for interactive systems — a user waiting for a quick response gets stuck behind a long batch job
  • Not optimal — does not minimize average waiting or turnaround time

86. What is the Round Robin (RR) Scheduling Algorithm?

Round Robin (RR) is a preemptive scheduling algorithm designed specifically for time-sharing systems. Each process is assigned a small, fixed unit of CPU time called a time quantum (q) or time slice. After its quantum expires, the process is preempted and moved to the back of the ready queue so the next process can run.

How It Works

The ready queue is maintained as a circular FIFO queue. The dispatcher picks the first process, runs it for at most q time units:

  • If the process finishes before q expires → it leaves voluntarily; next process starts immediately
  • If the process doesn't finish in q → timer interrupt fires; process preempted and added to the back of the queue

Time Quantum Selection

The time quantum size critically affects performance:

  • Too large → degenerates into FCFS; poor responsiveness
  • Too small → too many context switches; overhead dominates
  • Rule of thumb: 80% of CPU bursts should be shorter than q. Typical values: 10–100 ms.

Example (q = 3 ms)

Processes: P1 (burst = 10ms), P2 (burst = 4ms), P3 (burst = 5ms), all arrive at time 0.

| P1(0–3) | P2(3–6) | P3(6–9) | P1(9–12) | P2(12–13) | P3(13–15) | P1(15–18) | P1(18–19) |
Waiting: P1 = 9ms, P2 = 6ms, P3 = 8ms
Average Waiting Time = (9 + 6 + 8) / 3 = 7.67 ms

Advantages

  • Fair — every process gets equal CPU time in proportion
  • Good response time — no process waits longer than (n−1)×q ms
  • No starvation — circular queue guarantees every process runs

Disadvantages

  • Performance highly sensitive to time quantum choice
  • High context switch overhead if quantum is too small
  • Higher average turnaround time compared to SJF for the same workload

87. What is Reentrancy?

Reentrancy is the property of a function or program that allows it to be safely called again (re-entered) before its previous invocation has finished executing — either by the same thread (recursion), a different thread, or an interrupt service routine.

A reentrant function can be interrupted at any point in its execution, called again (concurrently or recursively), and both invocations will work correctly without interfering with each other.

Requirements for a Reentrant Function

  1. Does not use static or global variables that are modified during execution (or protects them with locks)
  2. Does not modify itself (self-modifying code is not reentrant)
  3. Does not call non-reentrant functions
  4. Stores all working state on the stack (local variables) — each invocation has its own stack frame

Reentrant vs. Non-Reentrant Example

// NON-REENTRANT (uses static variable — shared between calls)
int counter() {
    static int count = 0;   // shared across all invocations
    return ++count;
}

// REENTRANT (uses only local variables)
int add(int a, int b) {
    return a + b;            // no shared state; always safe
}

Why Reentrancy Matters in OS

Interrupt Handlers: An ISR may be interrupted by a higher-priority interrupt, re-entering the handler. The handler must be reentrant.

Multithreading: Multiple threads may simultaneously call the same library function. The function must be thread-safe (a superset of reentrancy) to avoid race conditions.

System Calls: OS kernel functions called by multiple processes must be reentrant (or protected by locks).

Reentrancy vs. Thread Safety

  • Reentrant — safe to re-enter before previous call completes (covers recursion + interrupt preemption)
  • Thread-safe — safe when called by multiple threads concurrently (uses synchronization)
  • All reentrant functions are thread-safe (if no global state is used), but not all thread-safe functions are reentrant (thread-safe may use locks; reentrant cannot use locks if it might be interrupted mid-lock)

88. What is a Scheduling Algorithm? Types of Scheduling Algorithms

A scheduling algorithm is the policy used by the OS's CPU scheduler to decide which process in the ready queue gets the CPU next. The choice of algorithm significantly affects system performance — throughput, response time, fairness, and CPU utilization.

Classification

A. Non-Preemptive Algorithms (Process voluntarily releases CPU)

1. FCFS (First Come First Served) Processes scheduled in arrival order. Simple; suffers from convoy effect. Implementation: FIFO queue.

2. SJF — Shortest Job First (Non-Preemptive) Process with shortest CPU burst scheduled first. Minimizes average waiting time. Suffers from starvation of long processes; requires knowing burst length in advance (hard to predict).

3. Priority Scheduling (Non-Preemptive) Highest-priority process runs first. Process runs to completion. Risk of starvation of low-priority processes. Fixed once admitted; no preemption.

B. Preemptive Algorithms (OS can interrupt a running process)

4. SRTF — Shortest Remaining Time First (Preemptive SJF) Preemptive version of SJF. When a new process arrives with a shorter remaining burst than the current process, current process is preempted. Optimal average waiting time; hard to implement (requires burst prediction).

5. Round Robin (RR) Each process gets a time quantum; preempted when it expires. Fair for time-sharing. Performance depends on quantum size.

6. Priority Scheduling (Preemptive) Higher-priority process arriving preempts lower-priority running process. Can cause starvation; solved with aging.

7. Multilevel Queue Scheduling Ready queue divided into multiple queues (foreground, background). Each queue has its own scheduling algorithm. Strict priority between queues — no process in lower queue runs while upper queue has processes.

8. Multilevel Feedback Queue Scheduling Like multilevel queue but processes can move between queues based on behavior (CPU-bound processes drop to lower-priority queues; I/O-bound processes stay in high-priority queues). Most flexible and widely used — Linux CFS is inspired by this.

9. Lottery Scheduling Each process is given lottery tickets. CPU given to winner of a random draw. Probabilistically fair; more tickets = more CPU time.

10. Fair-Share Scheduling CPU time allocated at the user level — each user gets equal share regardless of how many processes they run.

AlgorithmTypeStarvationBest For
FCFSNon-preemptiveNoBatch systems
SJFNon-preemptiveYesMinimizing avg wait
SRTFPreemptiveYesOptimal avg wait
Round RobinPreemptiveNoTime-sharing
PriorityBothYes (needs aging)Real-time, importance
Multilevel FeedbackPreemptiveNoGeneral purpose

89. What is Cascading Termination?

Cascading termination is the process by which, when a parent process terminates, all of its child (and descendant) processes are also automatically terminated by the operating system.

Why Cascading Termination Occurs

When a parent process exits, the OS checks if it has any existing child processes. In systems that implement cascading termination (like Windows), the OS does not allow children to continue existing without a parent — it terminates all children recursively before fully cleaning up the parent.

The reasoning is that child processes were created to serve the parent. Without the parent, the children may no longer have a meaningful purpose, and allowing them to continue could result in resource leaks (memory, file handles, CPU time).

How It Works (Step by Step)

  1. Parent process calls exit() or is killed
  2. OS identifies all direct children of the parent
  3. Each child is sent a termination signal (or killed directly)
  4. If those children themselves have children, the process recurses — cascading down the entire process tree
  5. Once all descendants are terminated, the parent is fully cleaned up

Operating System Differences

Windows: Implements cascading termination by default. When a job (process group) is terminated, all processes in the job are terminated.

Unix/Linux: Does NOT implement cascading termination by default. When a parent exits, children become orphans and are adopted by init/systemd (PID 1). They continue running. This is intentional — Unix uses orphan adoption as the standard mechanism.

Cascading Termination vs. Orphan Process

AspectCascading TerminationOrphan Process (Unix)
When parent diesAll children terminatedChildren continue running
Adopted by init?No — children are killedYes — init adopts orphans
Used byWindows (default)Unix/Linux (default)
Resource cleanupImmediateChildren clean up when they exit

Use Cases Where Cascading Termination is Useful

  • When a process tree represents a single application (e.g., IDE → compiler → linker); killing the IDE should stop all sub-processes
  • Preventing resource leaks from abandoned background workers
  • Job control in Windows job objects — entire job can be terminated atomically

Operating System — Memory Management, File Systems, Deadlocks & IPC


3. Memory Management

90. What is Memory Management?

Memory management is the OS function responsible for tracking, allocating, and reclaiming physical memory (RAM) across all running processes. It ensures every process has the memory it needs while preventing processes from interfering with each other's memory.

Goals

  • Efficiency — maximize RAM utilization; minimize wasted space
  • Isolation — each process sees only its own memory; cannot access others'
  • Transparency — each process behaves as if it has its own large, contiguous address space
  • Support for virtual memory — programs can use more memory than physically available

Key Functions

Address Translation — the MMU (Memory Management Unit) hardware converts logical (virtual) addresses used by programs into physical addresses in RAM, using page tables or segment tables.

Allocation — when a process starts or requests memory (malloc, new), the OS allocates a region. Strategies: first-fit (first large enough hole), best-fit (smallest sufficient hole), worst-fit (largest hole).

Deallocation — when a process exits or frees memory (free, delete), the OS reclaims it and marks it available.

Swapping — moves entire processes or individual pages between RAM and disk (swap space) when RAM is overloaded.

Fragmentation Management — uses paging, segmentation, or compaction to reduce wasted memory from fragmentation.


91. Explain the Concept of Paging

Paging is a memory management scheme that eliminates the need for contiguous physical memory allocation by dividing both physical and logical memory into fixed-size blocks.

  • Physical memory is divided into fixed-size blocks called frames
  • Logical (virtual) address space of a process is divided into same-size blocks called pages
  • A page table (one per process, maintained by OS) maps each page number to a physical frame number

Address Translation

A logical address is split into two parts:

Logical Address = [ Page Number (p) | Page Offset (d) ]
Physical Address = Frame Base Address + Offset

Example: With page size = 4 KB (2¹² bytes):

  • Logical address 0x3A5C → page number = 3, offset = 0xA5C
  • OS looks up page 3 in page table → frame 7 (say)
  • Physical address = frame 7 × 4096 + 0xA5C

Page Table

  • Stored in main memory (one per process)
  • The PTBR (Page Table Base Register) points to the current process's page table
  • Every memory access requires two memory accesses: one for the page table, one for the actual data
  • TLB (Translation Lookaside Buffer) caches recent page-to-frame translations to reduce this to ~one access on a hit

Key Benefits of Paging

  • No external fragmentation — any free frame can hold any page
  • Supports virtual memory — pages can be on disk (demand paging)
  • Easy sharing — two processes can map the same physical frame (shared libraries)
  • Process isolation — each process has its own page table; no accidental access to others' memory

Internal Fragmentation

Paging introduces internal fragmentation — the last page of a process may not be fully used (e.g., a process needing 4097 bytes with 4 KB pages uses 2 pages; the second page wastes 4095 bytes).


92. What is Segmentation?

Segmentation is a memory management scheme that divides a process's logical address space into variable-size segments based on the logical structure of the program — matching how programmers think about their programs.

Segments

Each program naturally consists of:

  • Code segment (text) — executable instructions
  • Data segment — global/static variables
  • Stack segment — function calls, local variables
  • Heap segment — dynamically allocated memory
  • Library segments — shared code

Address Structure

A segmented logical address has two components:

Logical Address = [ Segment Number (s) | Offset (d) ]

The OS maintains a Segment Table (one per process) with each entry containing:

  • Base — starting physical address of the segment
  • Limit — length of the segment

Translation: If offset < limitPhysical Address = Base + Offset; else → Segment Fault (protection violation).

Advantages

  • Matches programmer's logical view of memory
  • Easy to share entire logical units (e.g., share the code segment between processes running the same program)
  • Fine-grained protection (each segment can have different permissions: read-only code, read-write data)
  • No internal fragmentation — segments are exactly the size needed

Disadvantages

  • External fragmentation — variable-size segments leave holes in physical memory
  • Segment sizes can grow and need relocation
  • More complex than paging

Segmentation vs. Paging

Modern systems (x86-64) use primarily paging with segmentation as a legacy feature. Some architectures combine both: segments are divided into pages internally (MULTICS, Intel IA-32).


93. What is Virtual Memory?

Virtual memory is a memory management technique that gives each process the illusion of having a large, contiguous, private address space — even if physical RAM is smaller or fragmented.

Virtual memory works by storing only the actively used pages of a process in RAM, keeping the rest on secondary storage (disk/swap). Pages are loaded on demand when accessed.

How It Works

  • Each process has a virtual address space (e.g., 0 to 2⁴⁸ bytes on 64-bit systems)
  • The OS + MMU maintain a page table mapping virtual pages to physical frames
  • Pages not currently in RAM have their page table entries marked invalid
  • Accessing an invalid page triggers a page fault → OS loads the page from disk

Key Mechanisms

  • Demand Paging — pages loaded only when accessed, not all at startup
  • Page Replacement — when RAM is full and a new page is needed, an existing page is evicted to disk using algorithms like LRU, FIFO, or Optimal
  • Swap Space — dedicated disk area (or swap file) holding pages evicted from RAM

Benefits

  • Programs larger than RAM can execute
  • More processes fit in memory (higher multiprogramming)
  • Process isolation — each process has its own virtual address space
  • Memory sharing — shared libraries occupy one physical copy mapped into many virtual spaces
  • Copy-on-Write (COW) — forked processes share pages until one writes

Performance Concern

Virtual memory performs well only when the page fault rate is low. Heavy page faulting leads to thrashing — the system spends more time swapping than executing.

EAT = (1−p) × memory_access_time + p × page_fault_service_time


94. Internal vs. External Fragmentation

Fragmentation refers to wasted memory space that cannot be used efficiently.

Internal Fragmentation

Definition: Wasted memory inside an allocated block — memory is allocated but not all of it is used by the process.

Cause: Occurs when memory is allocated in fixed-size units (pages, partitions) and the process doesn't need the full unit.

Example: Page size = 4 KB. Process needs 5 KB → allocated 2 pages (8 KB) → wastes 3 KB inside the second page.

Where it occurs: Paging, fixed-size memory partitions, slab allocator.

External Fragmentation

Definition: Wasted memory between allocated blocks — enough total free memory exists to satisfy a request, but it is scattered in non-contiguous pieces.

Cause: Variable-size allocations/deallocations over time leave holes of different sizes scattered through memory.

Example: 3 free holes of 2 KB each (total 6 KB free), but a 5 KB request fails because no single hole is large enough.

Where it occurs: Segmentation, dynamic contiguous allocation (first-fit, best-fit), early memory systems.

Solution: Compaction (expensive), paging (eliminates it), coalescing free blocks.

AspectInternal FragmentationExternal Fragmentation
LocationInside allocated blockBetween allocated blocks
CauseFixed-size allocation unitsVariable-size allocations/deallocations
Where?Paging, fixed partitionsSegmentation, dynamic allocation
SolutionSmaller page sizesCompaction, paging
Total free memoryMay be sufficientAlways sufficient in total

95. What is a Page Fault?

A page fault is a hardware exception (interrupt) that occurs when a process accesses a virtual memory page that is not currently in physical RAM — its page table entry is marked invalid.

Types of Page Faults

Minor (Soft) Page Fault — the page is in memory but not mapped in the process's page table (e.g., a shared page not yet mapped for this process). No disk I/O needed; just update the page table. Very fast.

Major (Hard) Page Fault — the page is not in memory at all and must be loaded from disk (swap space or file system). Requires disk I/O — slow (milliseconds for HDD, microseconds for SSD).

Invalid Page Fault — the process accesses a completely invalid address (outside its address space). The OS sends a SIGSEGV (segmentation fault) signal and typically kills the process.

Page Fault Handling (Major Fault)

  1. CPU detects invalid page table entry → triggers page fault exception
  2. OS page fault handler checks if address is valid (if not → segfault)
  3. OS finds a free physical frame (if none available → run page replacement algorithm to evict a page)
  4. If evicted page is dirty (modified) → write it to disk first
  5. OS reads the needed page from disk into the free frame
  6. Update page table entry: set valid bit, record frame number
  7. Restart the faulting instruction (which now succeeds)

Performance Impact

One page fault can cost 8–20 ms (HDD) or ~100 µs (SSD). Since normal memory access is ~100 ns, even a rare page fault rate dramatically increases effective access time.


96. Page Replacement Algorithms

When a page fault occurs and no free frames are available, the OS must evict an existing page to make room. The choice of which page to evict is made by the page replacement algorithm.

FIFO — First In, First Out

Policy: Evict the page that has been in memory the longest (oldest page).

Implementation: Maintain a queue of pages in load order. Evict from front, add new pages to back.

Example: Frames = 3, Reference string: 7, 0, 1, 2, 0, 3, 0, 4

Page faults: 7(miss), 0(miss), 1(miss), 2(miss→evict 7), 0(hit), 3(miss→evict 0), 0(miss→evict 1), 4(miss→evict 2) = 6 faults

Drawback: Evicts old pages regardless of whether they are actively used. Suffers from Belady's Anomaly — more frames can sometimes cause more faults.

LRU — Least Recently Used

Policy: Evict the page that has not been used for the longest time.

Rationale: Based on temporal locality — pages used recently are likely to be used again soon.

Implementation: Stack-based (most recently used on top) or timestamps on each access.

Example (3 frames): Reference string: 7, 0, 1, 2, 0, 3, 0, 4

After 0,1,2 loaded: access 0(hit), then 3(miss→evict 1, LRU), access 0(hit), access 4(miss→evict 2)
Fewer faults than FIFO for most workloads

Advantages: Good approximation of optimal; immune to Belady's Anomaly.

Drawbacks: Exact LRU requires hardware support (timestamps on every access) or approximations (reference bits, clock algorithm). Overhead for tracking all accesses.

Optimal (OPT / Bélády's Algorithm)

Policy: Evict the page that will not be used for the longest time in the future.

Rationale: This is provably optimal — produces the fewest possible page faults for any reference string.

Drawback: Requires knowing the future — not implementable in a real OS. Used only as a theoretical benchmark to evaluate other algorithms.

Comparison

AlgorithmPolicyBelady's AnomalyImplementablePerformance
FIFOEvict oldestYes (susceptible)Yes (simple)Worst
LRUEvict least recently usedNoYes (with approximation)Good
OptimalEvict not-needed-longestNoNo (needs future)Best (theoretical)

Approximate LRU implementations: Reference bit algorithm, Second-Chance (Clock) algorithm, Additional-Reference-Bits algorithm.


97. What is Thrashing?

Thrashing is a severe performance degradation condition where the OS spends more time swapping pages in and out of memory than executing process instructions, resulting in near-zero useful throughput.

How Thrashing Occurs

  1. The OS increases multiprogramming (admits more processes to improve CPU utilization)
  2. Each process has insufficient frames to hold its working set (the set of pages it actively uses)
  3. Processes constantly generate page faults — loading a page evicts another that will soon be needed again
  4. CPU utilization drops because processes spend almost all their time waiting for page I/O
  5. The OS (wrongly) interprets low CPU utilization as a signal to admit even more processes → makes things worse
  6. System enters a cycle of continuous, futile page swapping

Thrashing and the Working Set Model

Working Set: The set of pages a process actively uses in a given time window (Δ). If the total working sets of all processes exceed available physical frames → thrashing.

Working Set Model (Denning, 1968): Track how many frames each process needs to prevent faulting. If Σ(working sets) > total frames → suspend or swap out some processes until the sum fits.

Symptoms of Thrashing

  • CPU utilization plummets (processes always waiting for I/O)
  • Disk activity (paging I/O) is constantly at or near 100%
  • System response becomes extremely slow
  • System monitor shows near-100% paging activity

Solutions to Thrashing

  • Reduce multiprogramming — suspend or swap out one or more processes
  • Add more RAM — the most direct solution
  • Use the Working Set Model — only keep processes whose full working sets fit in memory
  • Use Page Fault Frequency (PFF) control — if fault rate > upper threshold, give process more frames; if < lower threshold, reclaim frames

98. What is Fragmentation?

Fragmentation is the condition where available memory is broken into pieces that cannot be used efficiently, resulting in wasted memory capacity even when there is technically enough total free memory.

Types

Internal Fragmentation — wasted space inside an allocated memory block. Occurs when allocation units are larger than what the process needs. Example: allocating a 4 KB page when only 2.5 KB is needed wastes 1.5 KB inside that page.

External Fragmentation — wasted space between allocated blocks. Enough total memory is free but it's scattered in non-contiguous fragments. Example: three 2 KB free holes exist but a 5 KB request fails.

Data Fragmentation (File Fragmentation) — a file's data is stored in non-contiguous blocks on disk, increasing seek time.

Impact of Fragmentation

  • External fragmentation can make memory allocation fail even when total free memory is sufficient
  • Internal fragmentation wastes usable memory inside allocations
  • Both reduce system performance and effective memory capacity

Solutions

Fragmentation TypeSolutions
InternalSmaller allocation units; variable-size allocation
ExternalCompaction; paging (no external fragmentation); coalescing adjacent free blocks
File (disk)Defragmentation tools (Windows Defrag, Linux e2defrag)

99. Basic Function of Paging

The basic function of paging is to allow a process's logical (virtual) address space to be non-contiguous in physical memory — any free physical frame can hold any virtual page, regardless of their order or location.

Core Functions

1. Eliminate External Fragmentation Since every physical frame is the same size and any frame can hold any page, there is never a situation where total free space is sufficient but unusable due to fragmentation.

2. Enable Non-Contiguous Allocation A 10-page process doesn't need 10 consecutive frames in RAM. Its pages can be scattered across any 10 free frames anywhere in physical memory. The page table tracks the mapping.

3. Support Virtual Memory Pages not needed immediately can remain on disk. The page table entry's valid bit indicates whether a page is in RAM or on disk. A page fault loads it on demand.

4. Enable Process Isolation Each process has its own page table. The OS controls the mappings — one process cannot access another's pages because their page tables point to different physical frames.

5. Support Memory Sharing Multiple processes can have page table entries pointing to the same physical frame — enabling shared code segments (shared libraries, copy-on-write).

6. Simplify OS Memory Management The OS only needs to track which frames are free (using a frame table/bitmap), rather than managing complex variable-size holes.


100. How Does Swapping Result in Better Memory Management?

Swapping is the technique of moving entire processes (or individual pages) between RAM and secondary storage (disk/swap partition) to manage situations where memory demand exceeds physical RAM capacity.

How Swapping Works

  1. When the OS needs to free RAM (due to memory pressure), it selects a process (or pages) to swap out
  2. The process's memory contents are written to a dedicated swap area on disk
  3. The process's frames are freed for other uses
  4. When the swapped-out process needs to run again, the OS swaps it back in — allocates frames and reloads its memory from the swap area
  5. The process resumes from exactly where it was paused

Benefits of Swapping

1. Higher Degree of Multiprogramming More processes can exist simultaneously than would fit in RAM alone. While some run in RAM, others wait in swap. This keeps the CPU busier.

2. Flexibility in Process Management Long-running, low-priority background processes can be swapped out during peak periods and swapped back in when resources are available.

3. Memory Overcommitment The OS can allocate more virtual memory than physical RAM exists — because not all processes need their full allocation simultaneously. This is standard on Linux.

4. Better CPU Utilization If all in-memory processes are blocked (waiting for I/O), the OS swaps in a ready process from disk, keeping the CPU busy.

5. Foundation for Virtual Memory Page-level swapping (demand paging) is the modern, fine-grained evolution of whole-process swapping. Instead of swapping entire processes, only individual pages are moved — much more efficient.

Swap Space

  • On Linux: dedicated swap partition or swap file
  • On Windows: pagefile.sys — a reserved file on the primary disk
  • Size recommendation: Traditionally 2× RAM; modern systems with large RAM use less

101. What is the Best Page Size?

Choosing the optimal page size involves balancing several competing factors. There is no universally "best" page size — it depends on the workload and hardware characteristics.

Effects of Different Page Sizes

Smaller Page Size (e.g., 512 bytes – 2 KB)

  • Less internal fragmentation (last page wastes less space)
  • Finer granularity — only truly needed data loaded into RAM
  • More pages per process → larger page tables (more memory overhead for page tables)
  • More TLB entries needed → higher TLB miss rate
  • More page faults (smaller pages, more transfers needed)

Larger Page Size (e.g., 4 MB – 1 GB)

  • More internal fragmentation
  • Smaller page tables (fewer entries)
  • Better TLB coverage (one entry covers more memory)
  • Larger disk transfer per page fault (but fewer faults for sequential access)
  • Poor for sparse memory access patterns

Current Standard

Most modern systems use 4 KB pages as the standard size — a balance between the above trade-offs, established by extensive empirical research. Many modern CPUs also support huge pages (2 MB or 1 GB on x86-64) for specific use cases:

  • Database systems (large buffer pools)
  • Virtual machines (hypervisors)
  • High-performance computing

Factors Determining Best Page Size

  • Average process size — larger processes benefit from larger pages
  • Memory capacity — more RAM → can afford larger page tables → smaller pages are okay
  • Disk I/O speed — slower disk → prefer larger pages (fewer but larger transfers)
  • Locality of reference — high spatial locality → larger pages are fine
  • TLB size — small TLB → favor larger pages (better coverage per entry)

4. File Systems

102. What is a File System?

A file system is the component of the OS that organizes, stores, retrieves, names, and manages data on storage devices. It provides the abstraction of files (named data collections) and directories (organizational containers) to users and applications.

Core Concepts

File — a named, ordered sequence of bytes stored on disk. The file system tracks: name, location (disk blocks), size, type, owner, permissions, and timestamps (created, modified, accessed).

Directory — a special file containing a table of (name → file/directory reference) mappings. Organizes files into a hierarchical tree structure.

File System Structure (on disk):

  • Boot Block — bootstrap code for loading the OS
  • Superblock — global metadata: total blocks, free blocks, inode count, block size, file system type
  • Inode Table — array of inodes; one per file; stores file metadata and block pointers
  • Data Blocks — actual file content and directory entries

File System Responsibilities

  • Naming — maintain a namespace (path like /home/user/file.txt)
  • Space management — track which disk blocks are free (via bitmap or free list)
  • Metadata management — store permissions, timestamps, ownership per file
  • Reliability — journaling, checksums to recover from crashes
  • Performance — caching, prefetching, buffering to minimize disk I/O

Examples: ext4 (Linux), NTFS (Windows), APFS (macOS), FAT32/exFAT (removable media), ZFS, Btrfs, XFS.


103. FAT vs. NTFS vs. ext4

FAT (File Allocation Table)

A simple, old file system using a linked-list table to track file blocks. Variants: FAT12, FAT16, FAT32, exFAT.

  • No permissions — no user/group ownership or access control
  • No journaling — prone to corruption on unclean shutdown
  • Max file size: FAT32 = 4 GB; exFAT = 16 EB
  • Best for: USB drives, SD cards, cross-platform compatibility

NTFS (New Technology File System)

Microsoft's primary Windows file system since Windows NT.

  • Full permissions — NTFS ACLs (Access Control Lists) with per-user/group permissions
  • Journaling — transaction log ($LogFile) protects metadata from corruption
  • Compression & Encryption — built-in file/folder compression and EFS encryption
  • Large file support — theoretically 16 EB max file size
  • Best for: Windows system/data drives

ext4 (Fourth Extended File System)

The default Linux file system, evolved from ext2/ext3.

  • Full Unix permissions — user/group/other rwx + special bits (setuid, sticky)
  • Journaling — metadata journal (optional data journaling)
  • Extents — efficient large-file allocation (contiguous block groups)
  • Large volume support — up to 1 EB volume, 16 TB max file size
  • Best for: Linux system and data drives
FeatureFAT32NTFSext4
OSCross-platformWindowsLinux
Max File Size4 GB16 EB16 TB
PermissionsNoneFull ACLUnix rwx
JournalingNoYesYes
EncryptionNoYes (EFS)Via kernel
Cross-platformExcellentLimitedLimited

104. What is a Directory Structure?

A directory structure is the organizational framework that determines how files and directories are arranged and related to each other within a file system.

Types of Directory Structures

1. Single-Level Directory All files stored in one directory. Simple but impractical — all files from all users share one flat namespace. Name collisions are inevitable. Used in very early systems.

2. Two-Level Directory One directory per user; all users' directories stored in a master directory (MFD). Separates users but no organization within each user's files.

3. Tree-Structured Directory (Hierarchical) The most common structure — a tree with a single root directory. Each directory can contain files and subdirectories. Paths are either absolute (from root: /home/user/docs/file.txt) or relative (from current directory: docs/file.txt). Used by Unix/Linux, Windows, macOS.

4. Acyclic-Graph Directory Extends the tree by allowing shared directories/files — a file or directory can have multiple parent directories (hard links and symbolic links). Must prevent cycles (cycles cause infinite loops in traversal). Used in Unix with hard links.

5. General Graph Directory Allows cycles — maximum flexibility but requires cycle detection during traversal. Rarely used due to complexity.

Directory Operations

Create, delete, open, close, read (list contents), rename, link (create a hard or symbolic link), unlink (remove entry).


105. Inodes in Unix-Based Systems

An inode (index node) is a data structure used in Unix/Linux file systems that stores all metadata about a file — everything except the file's name and content.

What an Inode Contains

  • File type — regular file, directory, symbolic link, device, pipe, socket
  • Permissions — read/write/execute for owner, group, and others
  • Owner — user ID (UID) and group ID (GID)
  • File size — in bytes
  • Timestamps — atime (last access), mtime (last modification), ctime (last inode change)
  • Link count — number of hard links pointing to this inode
  • Block pointers — addresses of disk blocks storing the file's data:
    • 12 direct block pointers
    • 1 single indirect pointer (→ block of pointers)
    • 1 double indirect pointer (→ block of pointer blocks)
    • 1 triple indirect pointer (for very large files)

Key Facts

  • Every file and directory has exactly one inode
  • Inodes are identified by inode numbers — not file names
  • A directory entry maps a filename to an inode number — the name is stored in the directory, not in the inode
  • Multiple filenames (hard links) can point to the same inode — they are the same file
  • When a file is deleted, its inode is freed only when the link count reaches 0 AND no process has the file open

Inode Table

The inode table is a fixed-size array at the beginning of the file system partition. The number of inodes is set at file system creation time (mkfs). Running out of inodes prevents creating new files even if disk space is available.


106. What is RAID?

(RAID levels covered in detail in Q9 of Part 1 — see os_complete_medium.mdx)

RAID (Redundant Array of Independent Disks) combines multiple physical disks into one logical unit to improve performance, reliability, or both.

Core techniques:

  • Striping (RAID 0) — data split across multiple disks for parallel read/write performance
  • Mirroring (RAID 1) — data written to two or more disks identically for redundancy
  • Parity (RAID 5/6) — error-correction data distributed across disks to survive one or two disk failures
RAID LevelMin DisksSurvivesUse Case
RAID 02NothingMax performance
RAID 121 diskOS drives, critical data
RAID 531 diskServers, NAS
RAID 642 disksCritical storage
RAID 1041 per mirrorHigh-performance databases

107. What is a Journaling File System?

A journaling file system maintains a journal (transaction log) that records planned changes to the file system before actually making them. If a crash occurs mid-operation, the journal is replayed on recovery to bring the file system to a consistent state.

The Problem Without Journaling

A write operation (e.g., creating a file) involves multiple disk writes: update inode, update directory, update free space bitmap. If the system crashes between writes, the file system is left in an inconsistent state — inode says file exists, but directory doesn't reference it; disk blocks are allocated but no inode claims them. Recovery requires a full fsck scan (can take hours for large disks).

How Journaling Works

  1. Before writing: log the intended changes to the journal on disk (write-ahead logging)
  2. Commit: mark the journal entry as committed
  3. Apply: apply the changes to the actual file system data structures
  4. Checkpoint: mark the journal entry as completed; it can be overwritten

If a crash occurs before step 2 → transaction is incomplete; simply ignored on recovery. If a crash occurs between steps 2 and 3 → journal is replayed; changes reapplied.

Journaling Modes (ext3/ext4)

  • Journal mode — both metadata AND data written to journal first. Slowest but safest.
  • Ordered mode — data written to file system first, then metadata journaled. Default in ext4. Good balance.
  • Writeback mode — only metadata journaled; data written at any time. Fastest but data may be stale after crash.

Benefits

  • Fast recovery — replaying the journal takes seconds, not hours
  • Consistency — file system is always in a consistent state after recovery
  • No need for full fsck — only the journal needs to be checked

Examples of journaling file systems: ext3, ext4, NTFS, APFS, XFS, JFS, Btrfs.


Both create alternative names for files, but they work very differently.

A hard link is a direct directory entry that points to the same inode as the original file. Both the original name and the hard link name reference the same inode number — they are completely interchangeable.

  • Both names refer to the same file data (same inode, same blocks)
  • The file's link count in the inode is incremented
  • The file data persists as long as at least one hard link exists (link count > 0)
  • Cannot span file systems — inode numbers are only unique within one file system
  • Cannot link to directories (to prevent cycles in the directory tree)
  • Deleting the original doesn't affect the data — the hard link remains valid
ln original.txt hardlink.txt     # Create hard link

A symbolic link is a special file that contains a path string pointing to another file or directory. Like a shortcut in Windows.

  • It's a separate file with its own inode containing the target path
  • If the target file is deleted or moved, the symlink becomes a dangling link (broken)
  • Can span file systems — the path works across different partitions
  • Can link to directories
  • Accessing a symlink transparently redirects to the target
ln -s original.txt symlink.txt    # Create symbolic link
FeatureHard LinkSymbolic Link
InodeSame as originalOwn inode (contains target path)
Cross-filesystemNoYes
Link to directoryNoYes
If original deletedData persistsBecomes dangling (broken)
File sizeSame as originalSize of path string
Transparent accessYesYes

109. File Fragmentation and Performance

File fragmentation occurs when a file's data blocks are not stored contiguously on disk — the file is broken into fragments scattered across the disk.

Why Fragmentation Occurs

When a file is created, it is written to available free blocks. As files are created, extended, and deleted over time, free space becomes scattered. A new file (or growing file) is allocated into whatever free blocks are available — often non-contiguous.

Impact on Performance

HDDs (Hard Disk Drives): Severely affected. Reading a fragmented file requires the disk arm to seek to each fragment's location. Every seek takes ~4–10 ms. A file with 100 fragments may require 100 seeks → seconds instead of milliseconds. This is why HDD defragmentation matters.

SSDs (Solid State Drives): Minimally affected. SSDs have no moving parts; random access is nearly as fast as sequential access. Fragmentation has negligible performance impact on SSDs. Frequent defragmentation of SSDs is actually harmful (wears out NAND flash cells unnecessarily).

Solutions

  • Defragmentation (HDD) — reorganizes file blocks to be contiguous. Windows includes Disk Defragmenter; Linux has e2defrag (ext2) and btrfs fi defrag.
  • File system design — modern file systems use allocation strategies to minimize initial fragmentation:
    • ext4 extents — allocates large contiguous regions for files upfront
    • XFS — delays allocation until flush time; can allocate contiguously
    • NTFS — uses best-fit allocation and preallocation

110. What is a File Descriptor?

A file descriptor (fd) is a small non-negative integer used by a process to refer to an open file (or other I/O resource: pipe, socket, terminal). It is the handle through which all file operations (read, write, close) are performed.

How File Descriptors Work

  1. A process calls open("file.txt", O_RDONLY) → OS opens the file, creates an entry in the kernel's Open File Table, and returns an integer (the file descriptor) to the process
  2. The process uses that integer in subsequent calls: read(fd, buf, size), write(fd, buf, size)
  3. When done, the process calls close(fd) → OS removes the entry, frees the kernel resources

Standard File Descriptors

Every Unix process starts with three file descriptors pre-opened:

FDNameDefault Connection
0stdinKeyboard input
1stdoutTerminal output
2stderrTerminal error output

File Descriptor Table

Each process has its own file descriptor table (in its PCB). Each entry contains:

  • Pointer to an entry in the system-wide Open File Table
  • Flags (e.g., close-on-exec)

The Open File Table entry contains:

  • File offset (current position)
  • Access mode (read/write)
  • Reference count
  • Pointer to the inode (or vnode)

Key Properties

  • File descriptors are process-specific — fd 5 in process A and fd 5 in process B are independent
  • Inherited by child processes after fork() — parent and child share the same open file table entry (and thus the same file offset)
  • Can be duplicated with dup()/dup2() — used for I/O redirection (e.g., ls > file.txt)

111. open(), read(), write(), close() System Calls

These four system calls form the foundation of file I/O in Unix/Linux.

open(pathname, flags, [mode]) → fd

Purpose: Opens (or creates) a file and returns a file descriptor.

Key flags:

  • O_RDONLY — open for reading only
  • O_WRONLY — open for writing only
  • O_RDWR — open for reading and writing
  • O_CREAT — create file if it doesn't exist (requires mode)
  • O_TRUNC — truncate file to zero length on open
  • O_APPEND — all writes go to end of file

What it does internally: Checks permissions, allocates a file descriptor, creates an Open File Table entry, sets file offset to 0, returns fd.

read(fd, buf, count) → bytes_read

Purpose: Reads up to count bytes from the file referenced by fd into the buffer buf.

Returns: number of bytes actually read (may be less than count), 0 at EOF, -1 on error.

Advances the file offset by the number of bytes read.

write(fd, buf, count) → bytes_written

Purpose: Writes up to count bytes from buffer buf to the file referenced by fd.

Returns: number of bytes actually written, -1 on error.

Advances the file offset. If opened with O_APPEND, offset is set to end of file before each write (atomically).

Buffering: Writes may be buffered in the kernel page cache. Use fsync(fd) to force flush to disk.

close(fd)

Purpose: Closes the file descriptor fd, releasing the kernel resources.

What it does: Decrements reference count in Open File Table. If count reaches 0, flushes buffers and frees the entry. Removes fd from the process's descriptor table. The fd number may be reused by the next open().

Always close file descriptors! Unclosed fds are a resource leak — processes have a finite limit (typically 1024–65536 per process).


112. What is a Mount Point?

A mount point is a directory in the existing file system hierarchy where a new file system is attached (mounted). After mounting, the contents of the mounted file system appear as a subdirectory at that path.

How Mounting Works

  1. OS reads the target device's file system metadata (superblock)
  2. OS creates a mount table entry recording: device, mount point path, file system type, options
  3. The mount point directory's inode is updated to redirect lookups into the new file system's root
  4. Programs accessing the mount point path now transparently access the mounted device

Example:

# Before mounting: /mnt/usb is an empty directory
mount /dev/sdb1 /mnt/usb   # Mount USB drive at /mnt/usb
ls /mnt/usb                 # Lists files on the USB drive
umount /mnt/usb             # Unmount when done

Key Concepts

  • Root File System (/) — the primary file system mounted at / during boot by the kernel
  • Virtual File System (VFS) — a layer that abstracts all file systems behind a unified interface; mounting works transparently regardless of file system type
  • On Windows, drives are mounted at drive letters (C:, D:) instead of mount points
  • Linux can mount file systems within directories: e.g., /home on a separate partition, /tmp on tmpfs (RAM disk)
  • Bind mounts — mount a directory at another path (same file system, different access point)

113. Block Device vs. Character Device

Unix/Linux represents hardware devices as special files in /dev/. Devices are classified as either block or character devices based on how they transfer data.

Block Device

A block device stores data in fixed-size blocks (typically 512 bytes or 4096 bytes) and supports random access — any block can be read/written in any order.

  • Data transferred in blocks, not individual bytes
  • Supports seeking to any position
  • The OS maintains a buffer cache of recently accessed blocks to improve performance
  • File systems are built on top of block devices
  • Examples: Hard drives (/dev/sda), SSDs, USB storage, CD-ROMs, RAID arrays

Character Device

A character device transfers data as a stream of individual bytes, one character at a time, in sequential order. Does not support random access or seeking.

  • No buffer cache at the block level (though may have a small queue)
  • Data is consumed/produced in real time
  • Examples: Terminal (/dev/tty), keyboard, mouse, serial port (/dev/ttyS0), audio devices, /dev/null, /dev/random
FeatureBlock DeviceCharacter Device
Data unitFixed-size blocksIndividual bytes (stream)
Random accessYes (can seek)No (sequential)
Buffer cacheYes (kernel block cache)Generally no
File systemBuilt on block devicesN/A
ExamplesHDD, SSD, USB storageTerminal, keyboard, serial port

114. What is fsck?

fsck (File System Consistency Check) is a Unix/Linux utility that scans and repairs inconsistencies in a file system. It is typically run automatically at boot time after an unclean shutdown (power failure, kernel crash) or manually by an administrator.

Why fsck is Needed

Without journaling (or after journal failure), a file system can become inconsistent — allocated blocks not referenced by any inode, directory entries pointing to freed inodes, incorrect free block counts, etc. fsck detects and fixes these inconsistencies.

What fsck Checks and Repairs

  1. Superblock — validates and repairs the file system's global metadata
  2. Free block bitmap — reconciles which blocks are marked free vs. which are actually allocated
  3. Inode table — checks each inode for validity; resets reference counts
  4. Directory structure — verifies that all directory entries point to valid inodes; checks for cycles
  5. Link counts — recalculates and corrects link counts for all files
  6. Lost files — files with inode but no directory entry are moved to /lost+found/

Usage

fsck /dev/sda1          # Check a specific partition (must be unmounted first)
fsck -n /dev/sda1       # Check only, don't repair (dry run)
fsck -y /dev/sda1       # Repair automatically without prompting

Note: With journaling file systems (ext4, NTFS, XFS), fsck is rarely needed — the journal handles crash recovery in seconds. Full fsck may still be scheduled periodically (e.g., every 30 mount cycles in ext4) as a deep integrity check.


115. What is a Distributed File System?

A distributed file system (DFS) is a file system that allows files to be stored across multiple networked computers while providing users and applications a unified, transparent view — as if all files were on a single local file system.

Key Characteristics

  • Location transparency — users access files by name without knowing which server stores them
  • Concurrency — multiple clients can access/modify files simultaneously (with concurrency control)
  • Replication — files can be replicated across multiple servers for fault tolerance and performance
  • Scalability — capacity and performance scale by adding more servers

How It Works

A DFS client component on each machine intercepts file system calls and either serves them from a local cache or forwards them to the appropriate file server over the network. A namespace server (or distributed hash table) maps file names to server locations.

Examples

NFS (Network File System) — developed by Sun Microsystems. Widely used in Unix/Linux environments. Mounts remote directories over a network; transparent to applications. Stateless protocol (originally); NFSv4 adds stateful operations.

SMB/CIFS (Server Message Block) — Microsoft's network file sharing protocol. Used for Windows network shares and Samba on Linux. Basis for mapping network drives.

HDFS (Hadoop Distributed File System) — designed for storing very large files (GB to TB) across commodity hardware clusters. Optimized for batch processing; files split into 128 MB blocks replicated 3×. Powers Apache Hadoop.

GFS (Google File System) — Google's proprietary DFS; designed for massive scale, fault tolerance, and large sequential reads. Inspired HDFS.

Ceph — open-source, highly scalable distributed file system. Provides object storage, block storage, and POSIX file system interfaces. Used in OpenStack and Kubernetes environments.

GlusterFS — open-source scale-out NAS. Aggregates storage from multiple servers into a single global namespace.


116. Role of FAT in the FAT File System

(See also Q61 in Part 2 for detailed structure)

The File Allocation Table (FAT) is the central data structure of the FAT file system — an array stored near the beginning of the volume where each entry represents one cluster and holds the index of the next cluster in a file's chain.

Role and Functions

1. Free Space Tracking — entries containing 0x0000 represent free clusters. The OS scans the FAT to find available clusters for new file data.

2. File Block Linking — since FAT uses linked allocation, a file's data blocks don't need to be contiguous. The FAT provides the chain: start cluster → FAT[start] → FAT[FAT[start]] → ... → end-of-chain marker.

3. Bad Block Marking — entries containing 0xFFF7 (FAT32) indicate bad clusters that should be avoided.

4. End-of-Chain Marking0xFFFF (FAT16) or 0x0FFFFFFF (FAT32) marks the last cluster of a file.

5. Redundancy — the FAT is stored twice on the volume (FAT1 and FAT2) as a backup. If FAT1 is corrupted, FAT2 can be used for recovery.

Performance concern: To read a large file, the OS may need to traverse a long FAT chain — potentially visiting hundreds of FAT entries scattered across the table. This is why FAT performs poorly with heavily fragmented large files.


117. File System vs. Database System

Both file systems and database systems store and manage data, but they differ significantly in design, capabilities, and use cases.

FeatureFile SystemDatabase System
Data modelUnstructured files and directoriesStructured tables (relational), documents, graphs, etc.
Access methodBy filename and pathBy query (SQL, NoSQL queries)
Data granularityEntire filesIndividual records, rows, fields
Concurrency controlBasic (file locks)Full ACID transactions, MVCC
IndexingLimited (file name only)Extensive (B-trees, hash indexes on any column)
SearchBy name/path onlyBy content, conditions, joins
Data integrityNo constraintsConstraints (foreign keys, CHECK, NOT NULL)
Crash recoveryJournaling (metadata)Full transaction logging, point-in-time recovery
Multi-user accessBasic read/write locksSophisticated isolation levels (SERIALIZABLE, etc.)
Use caseStoring documents, media, executables, logsStructured business data, applications requiring queries

When to use a file system: Storing large binary files (videos, images, executables), logs, configuration files, or data with natural file-like structure.

When to use a database: Storing structured, relational data that needs to be queried, updated atomically, and accessed by multiple users concurrently.

Modern systems often combine both: a database stores structured metadata and indexes; the file system stores the actual file content (e.g., media platforms store video files on object storage but metadata in a database).


5. Deadlocks

118. What is a Deadlock?

(Covered in detail at Q45 in Part 2 — see os_complete_medium.mdx)

A deadlock is a condition where a set of processes are permanently blocked — each waiting for a resource held by another in the set, with no process able to proceed.

Classic example: Process A holds Resource 1 and waits for Resource 2. Process B holds Resource 2 and waits for Resource 1. Neither can proceed — they are deadlocked.

All four Coffman Conditions must hold: Mutual Exclusion, Hold and Wait, No Preemption, Circular Wait.


119. Four Necessary Conditions for Deadlock (Coffman Conditions)

(Covered in detail at Q41 in Part 2)

For a deadlock to occur, all four conditions must hold simultaneously:

1. Mutual Exclusion — at least one resource is non-shareable; only one process can use it at a time (e.g., a printer, a write lock).

2. Hold and Wait — a process holds at least one resource and is waiting to acquire additional resources held by other processes.

3. No Preemption — resources cannot be forcibly taken from a process; they are released only voluntarily when the process finishes using them.

4. Circular Wait — a circular chain of processes exists: P0 waits for P1's resource, P1 waits for P2's, ..., Pn waits for P0's.

Prevention strategy: Eliminate any one of these four conditions by system design.


120. Deadlock Handling Strategies

1. Deadlock Prevention

Proactively design the system so that at least one Coffman condition can never hold:

  • Eliminate Mutual Exclusion — use shareable resources where possible (read-only resources can be shared). Not always feasible (printers, write locks must be exclusive).
  • Eliminate Hold and Wait — require processes to request all resources at once before starting. Or require releasing all held resources before requesting new ones. Drawback: low resource utilization; starvation.
  • Allow Preemption — if a process holding resources must wait for another resource, preempt all its held resources and add them to the waiting list. Practical only for resources whose state can be saved and restored (CPU registers, yes; printers, no).
  • Eliminate Circular Wait — impose a total ordering on all resource types. Require processes to request resources strictly in increasing order. This makes circular chains impossible.

2. Deadlock Avoidance

The OS dynamically checks each resource request and only grants it if the resulting state is safe (a safe execution sequence for all processes still exists).

  • Requires processes to declare their maximum resource needs in advance
  • The Banker's Algorithm is the primary avoidance algorithm
  • More flexible than prevention but adds runtime overhead

3. Deadlock Detection and Recovery

Allow deadlocks to occur but periodically run a detection algorithm to find them, then recover:

  • Detection: Run the resource allocation graph cycle-detection algorithm (single-instance) or the deadlock detection algorithm (multi-instance)
  • Recovery options:
    • Process termination — kill one or more deadlocked processes (all at once or one at a time)
    • Resource preemption — forcibly take resources from a victim process; rollback to checkpoint

4. Deadlock Ignorance (Ostrich Algorithm)

Pretend deadlocks don't exist — ignore the problem entirely. Justified when deadlocks are so rare that the cost of prevention/detection outweighs the benefit. Most general-purpose OSes (Linux, Windows) use this approach, relying on applications to avoid deadlocks by design.


121. Banker's Algorithm

(Covered in detail at Q38 in Part 2)

The Banker's Algorithm (Dijkstra) is a deadlock avoidance algorithm that only grants resource requests when the resulting state is safe.

Safe state — a state where a safe sequence exists: an ordering of all processes in which each can complete using currently available resources plus those released by preceding processes.

Data structures:

  • Available[m] — free resource instances
  • Max[n][m] — maximum demand per process
  • Allocation[n][m] — currently allocated
  • Need[n][m] = Max − Allocation

On each request: Tentatively grant → run safety algorithm → if safe, confirm; if unsafe, rollback and block.


122. Resource Allocation Graph

(Covered in detail at Q44 in Part 2)

A Resource Allocation Graph (RAG) is a directed graph representing the state of resource allocation and requests.

  • Circles = processes; Rectangles = resources (dots = instances)
  • P→R (request edge) = process waiting for resource
  • R→P (assignment edge) = resource allocated to process

Deadlock detection:

  • Single-instance resources: cycle = deadlock
  • Multi-instance resources: cycle is necessary but not sufficient

123. Deadlock Prevention vs. Deadlock Avoidance

AspectDeadlock PreventionDeadlock Avoidance
ApproachEliminate one Coffman condition by system designDynamically check each request; deny if state becomes unsafe
When appliedAt system design time (before runtime)At runtime (each resource request)
Knowledge requiredNone beyond system designProcesses must declare max resource needs
OverheadNo runtime overheadRuntime overhead per request (safety algorithm)
Resource utilizationLower (overly conservative constraints)Higher (resources used when safe)
FlexibilityLow (rigid rules)Higher (request-by-request decisions)
ExampleRequire all resources requested at onceBanker's Algorithm
Starvation riskYes (e.g., hold-and-wait elimination)Possible but less common

124. What is the Ostrich Algorithm?

The Ostrich Algorithm is a deadlock handling strategy that simply ignores the deadlock problem entirely — like an ostrich burying its head in the sand.

Rationale

If deadlocks are extremely rare and the cost of:

  • Prevention (reduced resource utilization, starvation risks, complex constraints)
  • Avoidance (advance knowledge of max needs, runtime overhead)
  • Detection + Recovery (periodic algorithm execution, process termination overhead)

...is greater than the cost of occasionally rebooting or killing processes when a deadlock is detected manually, then ignoring the problem is pragmatically justified.

Where It's Used

  • Most general-purpose operating systems — Linux, Windows, macOS do not have system-wide deadlock detection/prevention mechanisms for user-level processes
  • They rely on application developers to avoid deadlocks through correct lock ordering, lock timeouts, and good design
  • The OS itself carefully avoids deadlocks in its own kernel code

When It's NOT Acceptable

  • Real-time systems — a deadlocked control system could cause catastrophic failure
  • Safety-critical systems — aircraft, medical devices, nuclear plant controllers
  • Database systems — databases implement deadlock detection and resolution (deadlock victim is rolled back and retried)

125. Livelock vs. Deadlock

Livelock

A livelock is a situation where two or more processes continuously change their state in response to each other but make no actual progress toward completing their tasks.

Processes are NOT blocked (they are actively running and responding), but they cycle through states without ever resolving the conflict.

Classic analogy: Two people walking toward each other in a narrow hallway. Each steps aside to let the other pass. But they both step to the same side simultaneously, then both step back. They repeat this forever — both moving, neither making progress.

Example in OS:

  • Process A requests resource X, sees it's unavailable, releases resource Y, and retries
  • Process B requests resource Y, sees it's unavailable, releases resource X, and retries
  • Each keeps releasing and re-requesting in sync — indefinitely

Solution: Add randomized back-off delays so processes don't perfectly synchronize their retries. Ethernet's CSMA/CD uses this approach.

Livelock vs. Deadlock

AspectDeadlockLivelock
Process stateBlocked (waiting)Active (running but cycling)
CPU usageNo CPU used (processes are waiting)CPU is consumed (processes keep running)
ProgressNoneNone
DetectabilityEasier (blocked processes visible)Harder (processes appear to be doing work)
ResolutionTerminate/preempt processesRandomized retry delays

126. Deadlock vs. Starvation

AspectDeadlockStarvation
DefinitionSet of processes permanently blocked due to circular resource waiting A process is perpetually denied resources despite being eligible
CauseAll four Coffman conditions hold simultaneouslyScheduling bias (always scheduling higher-priority processes first)
Processes involvedMultiple processes in a cycleCan affect a single process
Other processesAll processes in the deadlock are blockedOther processes run normally
ResolutionProcess termination, resource preemptionAging (gradually increase priority), fair scheduling
Eventual progress?No process in the deadlock ever progressesSome processes progress; the starved one doesn't

127. Handling Deadlocks with Timeouts

Timeouts are a practical, simple mechanism for deadlock handling — a process that has been waiting for a resource longer than a threshold time is assumed to be potentially deadlocked and takes action.

How Timeout-Based Deadlock Handling Works

  1. When a process requests a resource, it starts a timer
  2. If the resource is granted before the timer expires → proceed normally
  3. If the timer expires before the resource is granted → assume deadlock and execute a recovery action:
    • Abort the waiting operation and return an error to the application
    • Release all held resources and retry the entire operation from scratch
    • Rollback to the last consistent state (if transaction support exists)

Advantages

  • Simple to implement — no complex deadlock detection algorithm needed
  • Works well for network and distributed systems where true deadlock detection is expensive
  • Natural fit for database systems (transaction timeout + rollback + retry)

Disadvantages

  • False positives — a process may be wrongly assumed deadlocked if it's just slow (heavy I/O, slow network). It may be aborted unnecessarily.
  • False negatives — a deadlock may persist if all involved processes time out at the same time and all retry simultaneously (could livelock)
  • Choosing timeout value is difficult — too short causes frequent false positives; too long delays deadlock detection

Real-World Use

  • Database systems (MySQL, PostgreSQL, SQL Server) use lock timeouts extensively — queries that can't acquire a lock within N seconds are rolled back and the transaction is retried
  • Distributed systems (microservices, Zookeeper) use request timeouts with circuit breakers
  • Network protocols use timeouts for detecting lost connections and retransmitting

128. Wait-Die and Wound-Wait Schemes

Wait-Die and Wound-Wait are timestamp-based deadlock prevention schemes used primarily in database systems to handle conflicting lock requests. Each transaction is assigned a timestamp at its start — older transactions have smaller timestamps.

Wait-Die (Non-Preemptive)

Rule: If an older transaction (lower timestamp) requests a resource held by a younger transaction → it waits. If a younger transaction requests a resource held by an older transaction → it dies (is aborted and restarted).

If T_i requests resource held by T_j:
  If T_i is older (smaller timestamp) → T_i waits
  If T_i is younger (larger timestamp) → T_i dies (aborts + restarts with original timestamp)

Characteristic: Old transactions wait; young transactions die. Only older transactions preempt younger ones through "letting younger die."

Wound-Wait (Preemptive)

Rule: If an older transaction requests a resource held by a younger transaction → the younger is wounded (preempted/aborted). If a younger transaction requests a resource held by an older transaction → it waits.

If T_i requests resource held by T_j:
  If T_i is older → T_j is wounded (aborted + restarted); T_i gets the resource
  If T_i is younger → T_i waits

Characteristic: Old transactions preempt (wound) younger ones; young transactions wait for older ones.

Comparison

FeatureWait-DieWound-Wait
Old requests Young's resourceOld waitsYoung is aborted (wounded)
Young requests Old's resourceYoung dies (aborts)Young waits
Who gets preemptedYounger transactionsYounger transactions
Preemption typeNon-preemptive (older waits)Preemptive (older wounds younger)

Common Property

Both schemes prevent circular wait (the 4th Coffman condition) and guarantee no deadlock. Aborted transactions restart with their original timestamp, so they eventually become the oldest transaction and won't die/be wounded again.


129. What is a Safe State?

In the context of deadlock avoidance, a safe state is a system state in which there exists at least one safe sequence — an ordering of all processes such that each process can obtain all the resources it needs to complete, using the currently available resources plus the resources released by all processes that precede it in the sequence.

Formal Definition

A state is safe if there exists a safe sequence <P1, P2, ..., Pn> such that for each process Pi, the resources Pi still needs can be satisfied by:

  • Currently available resources
  • Resources held by all Pj where j < i (processes that complete before Pi)

Safe State Guarantee

If the system is in a safe state → deadlock is impossible. Every process can eventually complete.

If the system is in an unsafe state → deadlock is possible but not certain (it depends on actual future resource requests).

The Banker's Algorithm maintains the system in a safe state by refusing resource requests that would transition the system from safe to unsafe.

Example

3 processes (P1, P2, P3), 12 total instances of one resource type:

  • P1 holds 2, max needs 9, needs 7 more
  • P2 holds 3, max needs 4, needs 1 more
  • P3 holds 2, max needs 7, needs 5 more
  • Available = 12 − (2+3+2) = 5 free

Safe sequence: P2 (needs 1, gets it, completes, releases 4) → Available=9; P3 (needs 5, gets it, completes, releases 7) → Available=16; P1 (needs 7, gets it, completes). Safe state!


130. Single-Instance vs. Multi-Instance Resources in Deadlock

Single-Instance Resources

Each resource type has exactly one instance (e.g., one printer, one specific database record).

Deadlock detection: Use the Resource Allocation Graph (RAG). A cycle in the graph = deadlock. This is a necessary and sufficient condition.

Detection is simple and fast — just check for cycles (DFS on the graph, O(V+E)).

Example: P1 holds R1 and requests R2; P2 holds R2 and requests R1 → cycle = deadlock.

Multi-Instance Resources

Each resource type has multiple instances (e.g., 5 printers, 10 database connection slots, 8 GB of RAM).

Deadlock detection: A cycle in the RAG is necessary but not sufficient — a cycle may exist without deadlock if some process can still complete and release resources to break the cycle.

Must use the deadlock detection algorithm (similar to the Banker's safety algorithm):

Work = Available
For each process Pi with Finish[i] = false:
  If Need[i] <= Work: execute Pi, Work += Allocation[i], Finish[i] = true
If any Finish[i] == false → those processes are deadlocked

This is O(n² × m) — more expensive than simple cycle detection.


6. Inter-Process Communication (IPC)

131. What is IPC?

(Covered in Q6 of Part 1 — see os_complete_medium.mdx)

IPC (Inter-Process Communication) is the set of mechanisms provided by the OS that allow separate processes (which run in isolated address spaces) to communicate, coordinate, and share data with each other.

Why IPC is needed: Processes cannot directly access each other's memory (process isolation). The OS provides controlled channels for processes to exchange information.

Two fundamental models:

  • Shared Memory — processes establish a shared memory region; communication happens via reads/writes to that region (fast, but needs synchronization)
  • Message Passing — processes communicate by sending/receiving explicit messages through the OS (simpler, OS handles synchronization, but slower)

132. IPC Mechanisms

Pipes

Unidirectional byte-stream channel. Output of one process → input of another.

  • Anonymous pipes — in-memory, require parent-child relationship, destroyed when closed
  • Named pipes (FIFOs) — have a filesystem path, allow unrelated processes to communicate, persist until deleted
  • ls | grep .txt is a classic pipe example

Message Queues

A kernel-managed linked list of messages. Processes send/receive typed messages without needing to be synchronized.

  • FIFO ordering (or priority-based)
  • Messages remain in the queue until read — sender doesn't need to wait for receiver
  • Survives sender/receiver termination (until explicitly deleted)

Shared Memory

The OS maps the same physical memory pages into two or more processes' address spaces. Communication happens via direct memory reads/writes — fastest IPC mechanism (no data copying or system call overhead).

  • Requires explicit synchronization (semaphores or mutexes) to prevent race conditions
  • Created with shmget()/shmat() (POSIX) or mmap(MAP_SHARED, ...)

Sockets

Bidirectional communication endpoints. Support both local (Unix domain sockets) and network (TCP/UDP) communication.

  • TCP sockets: reliable, ordered, connection-oriented
  • UDP sockets: unreliable, unordered, connectionless (faster for some use cases)
  • Foundation of all network programming
MechanismSpeedComplexityPersistenceScope
Pipe (anonymous)MediumLowTemporaryParent-child only
Named PipeMediumLow-MediumUntil deletedSame machine
Message QueueMediumMediumUntil deletedSame machine
Shared MemoryFastestHigh (needs sync)Until deletedSame machine
Socket (Unix)FastMediumUntil closedSame machine
Socket (TCP/UDP)MediumMediumUntil closedNetwork-wide

133. What is a Semaphore?

(Covered in Q12 of Part 1 and Q16 of Part 1)

A semaphore is an integer-based synchronization primitive used to control access to shared resources in concurrent programs. Introduced by Edsger Dijkstra (1965).

Two atomic operations:

  • wait(S) / P(): If S > 0, decrement S and proceed. If S = 0, block until S > 0.
  • signal(S) / V(): Increment S. If processes are blocked, wake one.

Binary Semaphore: Value 0 or 1 — acts like a mutex. Ensures mutual exclusion.

Counting Semaphore: Value 0 to N — manages a pool of N resources. Allows up to N processes into the critical section simultaneously.

Key: Both operations must be atomic — they must complete without interruption.


134. Mutex vs. Semaphore

FeatureMutexSemaphore
Full nameMutual Exclusion LockSemaphore (counting or binary)
Value rangeBinary (locked/unlocked)Integer (0 to N)
OwnershipOwned by specific thread

— only the acquirer can release

No ownership

— any thread can signal

Primary useMutual exclusion (protect critical section)Signaling + resource counting
Binary semaphore = mutex?Not exactly — mutex has ownership; binary sem doesn'tBinary semaphore can be used like a mutex but lacks ownership semantics
Recursive lockingSome mutexes support it (recursive mutex)Not applicable
Priority inversion handlingSome implementations support priority inheritanceGenerally no
Typical useThread synchronization within a processSignaling between processes; resource pools

Key distinction: A mutex has the concept of ownership — the thread that locks it must be the one to unlock it. A semaphore can be signaled by any thread/process, making it suitable for producer-consumer signaling (producer signals, consumer waits).


135. What is a Race Condition?

A race condition occurs when two or more processes or threads access shared data concurrently and the final result depends on the unpredictable order of execution (the "race" between threads), leading to incorrect, non-deterministic outcomes.

Classic Example

// Shared variable: counter = 5
// Thread A and Thread B both execute: counter++

// Thread A:          Thread B:
load counter (5)
                      load counter (5)
increment → 6
                      increment → 6
store 6
                      store 6
// Result: counter = 6 (should be 7!)

counter++ is NOT atomic — it's a read-modify-write sequence. If interrupted between reads and writes, updates are lost.

Why Race Conditions Are Dangerous

  • Results are non-deterministic — the bug may rarely manifest but causes intermittent failures
  • Extremely hard to reproduce and debug (depends on timing, CPU scheduling, CPU speed)
  • Can corrupt data structures, cause security vulnerabilities, or crash programs

Prevention

  • Mutex locks — protect critical sections with lock()/unlock()
  • Atomic operations — use hardware-level atomic instructions (compare-and-swap, fetch-and-add)
  • Immutable data — data that never changes needs no synchronization
  • Thread-local storage — give each thread its own copy of data

136. Advantages of Semaphores

1. Generality — binary semaphores provide mutual exclusion; counting semaphores manage resource pools. One mechanism solves many synchronization problems.

2. Atomic operationswait() and signal() are atomic by design, making them safe for concurrent use.

3. No busy-waiting (blocking semaphores) — when a process cannot proceed, it is put to sleep (blocked), freeing the CPU for other processes. No CPU cycles wasted spinning.

4. Works across processes — unlike mutexes (which are typically intra-process), System V semaphores and POSIX named semaphores work across separate processes.

5. Solves classic problems — directly models and solves Producer-Consumer, Readers-Writers, Dining Philosophers problems elegantly.

6. No starvation (with fair implementation) — with FIFO wake-up ordering, every blocked process eventually gets the semaphore.

7. Flexible signaling — a process can signal a semaphore it never waited on, enabling decoupled producer-consumer signaling (producer doesn't need to know the consumer).


137. Drawbacks of Semaphores

1. Programming complexity — developers must manually call wait() and signal() in exactly the right places. Missing a signal() causes a process to block forever; missing a wait() causes a race condition.

2. Deadlock risk — if wait() is called on two semaphores in different orders by different processes, deadlock can occur. Semaphores provide no automatic deadlock prevention.

3. Priority inversion — a low-priority process holding a semaphore blocks a high-priority process. Semaphores don't inherently support priority inheritance.

4. No ownership — unlike mutexes, any process can call signal() on a semaphore. A misbehaving process signaling at the wrong time can corrupt synchronization logic.

5. Difficult to reason about — in large systems with many semaphores, proving correctness is hard. wait() and signal() scattered through code are hard to audit.

6. Spinlocks (busy-wait semaphores) — in some implementations, processes spin-wait while checking the semaphore, wasting CPU cycles.

7. No high-level abstraction — semaphores are low-level primitives. Mistakes are easy. Higher-level constructs (monitors, condition variables) are safer but must be implemented on top of semaphores.


138. Named Pipe (FIFO) vs. Unnamed Pipe

Unnamed Pipe (Anonymous Pipe)

  • Created with pipe(fd[2]) system call
  • Exists only in kernel memory — no file system entry
  • Requires a parent-child relationship (child inherits the pipe's file descriptors after fork())
  • Temporary — destroyed when all file descriptors referring to it are closed
  • Unidirectional (one read end, one write end)
  • Cannot be accessed by unrelated processes

Named Pipe (FIFO)

  • Created with mkfifo("path", mode) or mknod
  • Has a visible path in the file system (e.g., /tmp/mypipe)
  • Can be used by any two processes — they just open() the path
  • Bidirectional use possible (though each end is unidirectional in practice)
  • Persists in the file system until explicitly unlink()'d
  • Behaves like a file for open()/read()/write() operations
FeatureUnnamed PipeNamed Pipe (FIFO)
Creationpipe()mkfifo()
File system entryNoYes (visible path)
Process relationshipParent-child requiredAny two processes
LifetimeUntil all FDs closedUntil unlink() or reboot
DirectionUnidirectionalUnidirectional (typically)
Access by nameNoYes (open by path)

139. Synchronous vs. Asynchronous IPC

Synchronous IPC (Blocking)

In synchronous IPC, the sending or receiving process blocks (waits) until the communication operation completes.

  • Blocking send: Sender blocks until the message is received (or placed in a buffer)
  • Blocking receive: Receiver blocks until a message is available
  • Simpler to reason about — after send() returns, you know the message was delivered
  • Naturally synchronizes processes — both sides coordinate in lock-step
  • Drawback: Wasted CPU time while blocked; can lead to deadlock if both sides try to receive simultaneously

Examples: write() to a full pipe blocks; read() from an empty pipe blocks; TCP send() with full kernel buffer blocks.

Asynchronous IPC (Non-Blocking)

In asynchronous IPC, the sending process returns immediately without waiting for the message to be received.

  • Non-blocking send: Sender puts message in buffer and continues immediately
  • Non-blocking receive: Returns immediately with data if available, or error if not
  • Better CPU utilization — sender does other work while message travels
  • More complex — sender must handle cases where delivery is not yet confirmed
  • Requires callbacks, polling, or event loops to know when communication completes

Examples: Message queues (sender continues; receiver reads later); UDP sockets; asynchronous I/O (aio_read, aio_write); O_NONBLOCK flag on file descriptors.

AspectSynchronous (Blocking)Asynchronous (Non-Blocking)
Sender behaviorWaits for delivery/acknowledgmentReturns immediately
Receiver behaviorWaits for messageReturns immediately (error if no data)
ComplexitySimplerMore complex
CPU efficiencyLower (CPU blocked)Higher
RiskDeadlock possibleRace conditions if not handled

140. What is a Message Queue?

A message queue is a kernel-managed data structure that provides an asynchronous message-passing mechanism between processes. Messages are placed in the queue by a sender and retrieved by a receiver at a later time — the sender and receiver do not need to be active simultaneously.

How It Works

  1. A process creates a message queue using msgget() (System V) or mq_open() (POSIX)
  2. A sender calls msgsnd() — the message (with a type and data) is appended to the queue
  3. A receiver calls msgrcv() — reads and removes a message from the queue (can filter by type)
  4. The queue persists in the kernel until explicitly deleted with msgctl(IPC_RMID) or system reboot

Key Properties

  • Persistence — messages remain in the queue even if the sender exits before the receiver reads them
  • Buffering — queue has a maximum capacity; sender blocks (or gets error) if queue is full
  • Message types — each message has a type field; receivers can selectively read by type
  • No synchronization needed — the queue itself is thread-safe; no external locking required
  • Decoupling — sender and receiver are independent; they don't need to coordinate timing

Use Cases

  • Inter-process pipelines where processes run at different speeds
  • Task queues in multi-process/multi-server architectures
  • Event notification systems
  • Foundation of modern messaging systems (RabbitMQ, Kafka are evolved versions of this concept)

141. Shared Memory and Its Implementation

Shared memory is the fastest IPC mechanism — two or more processes map the same physical memory pages into their respective virtual address spaces. Communication happens via direct memory reads/writes with no kernel involvement after setup.

POSIX Shared Memory Implementation

// Process A (Creator/Writer):
int fd = shm_open("/myshm", O_CREAT | O_RDWR, 0666);
ftruncate(fd, 4096);               // set size to 4 KB
void *ptr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
strcpy(ptr, "Hello from A");       // write directly to shared memory

// Process B (Reader):
int fd = shm_open("/myshm", O_RDONLY, 0666);
void *ptr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);
printf("%s\n", (char*)ptr);        // reads "Hello from A"

System V Shared Memory (Older Interface)

int shmid = shmget(key, size, IPC_CREAT | 0666);
void *ptr = shmat(shmid, NULL, 0);  // attach
// use ptr directly
shmdt(ptr);                          // detach
shmctl(shmid, IPC_RMID, NULL);       // delete

Critical Requirement: Synchronization

Shared memory itself provides NO synchronization. Without it, concurrent writes cause race conditions. Must use:

  • Semaphores — POSIX or System V semaphores
  • Mutexes in shared memory — POSIX mutex with PTHREAD_PROCESS_SHARED attribute
  • Read-Write locks — for reader-favoring workloads

142. Blocking vs. Non-Blocking IPC

(Related to Q139 — Synchronous vs. Asynchronous IPC)

Blocking IPC

An IPC operation that causes the calling process to suspend execution until the operation completes.

Blocking send: Process blocks until the message has been received by the destination (or buffered in kernel).

Blocking receive: Process blocks until a message is available in the queue or pipe.

Example: read(pipe_fd, buf, size) — blocks if pipe is empty until data is written.

When to use: When the process has nothing else to do until the communication completes; simpler logic.

Non-Blocking IPC

An IPC operation that returns immediately whether or not the operation could complete, along with a status code.

Non-blocking send: If the channel is full, returns immediately with an error (e.g., EAGAIN).

Non-blocking receive: If no message is available, returns immediately with EAGAIN instead of blocking.

Set with: O_NONBLOCK flag on file descriptors; MSG_DONTWAIT flag on socket calls; IPC_NOWAIT flag on msgrcv().

When to use: When the process manages multiple IPC channels (use with select(), poll(), or epoll() for event-driven I/O); servers handling thousands of clients.


143. What is a Condition Variable?

A condition variable is a synchronization primitive that allows a thread to wait (block) until a specific condition becomes true, and to be signaled (woken up) when that condition changes.

Condition variables are always used together with a mutex — the mutex protects the shared state; the condition variable provides the waiting/signaling mechanism.

Operations

  • wait(cond, mutex) — atomically releases the mutex and suspends the thread; when woken, re-acquires the mutex before returning
  • signal(cond) — wakes up one thread waiting on the condition variable
  • broadcast(cond) — wakes up all threads waiting on the condition variable

Example: Producer-Consumer with Condition Variables

// Shared state
int buffer_full = 0;
pthread_mutex_t mutex;
pthread_cond_t not_full, not_empty;

// Producer:
pthread_mutex_lock(&mutex);
while (buffer_full) pthread_cond_wait(&not_full, &mutex);  // wait if full
produce_item();
buffer_full = 1;
pthread_cond_signal(&not_empty);   // tell consumer item is ready
pthread_mutex_unlock(&mutex);

// Consumer:
pthread_mutex_lock(&mutex);
while (!buffer_full) pthread_cond_wait(&not_empty, &mutex); // wait if empty
consume_item();
buffer_full = 0;
pthread_cond_signal(&not_full);    // tell producer buffer is free
pthread_mutex_unlock(&mutex);

Why while Instead of if?

Always use while (not if) to check the condition after waking — spurious wakeups (a thread waking up for no reason) can occur; re-checking the condition guards against this.


144. The Producer-Consumer Problem

The producer-consumer problem (also called the bounded-buffer problem) is a classic synchronization problem where:

  • A producer process generates data items and places them in a fixed-size shared buffer
  • A consumer process takes items from the buffer and processes them
  • The buffer has a maximum capacity (N items)

Constraints

  • Producer must wait if the buffer is full
  • Consumer must wait if the buffer is empty
  • Buffer access must be mutually exclusive — only one process accesses the buffer at a time

Solution Using Semaphores

Semaphores:
  mutex = 1          // binary: mutual exclusion for buffer access
  empty = N          // counting: number of empty slots
  full = 0           // counting: number of filled slots

Producer:
  wait(empty)        // wait if buffer full (empty slots = 0)
  wait(mutex)        // enter critical section
  add item to buffer
  signal(mutex)      // exit critical section
  signal(full)       // one more full slot

Consumer:
  wait(full)         // wait if buffer empty (full slots = 0)
  wait(mutex)        // enter critical section
  remove item from buffer
  signal(mutex)      // exit critical section
  signal(empty)      // one more empty slot

Solutions via Other IPC Mechanisms

  • Pipes — natural producer-consumer; write end produces, read end consumes; pipe capacity is the buffer
  • Message Queues — producer sends messages; consumer receives them; queue is the buffer
  • Shared Memory + Semaphores — explicit shared buffer in shared memory; semaphores for synchronization

145. Direct vs. Indirect Communication in IPC

Direct Communication

Processes explicitly name each other in their communication calls — the sender and receiver specify who they're talking to.

send(Process_B, message);     // send directly to Process B
receive(Process_A, &message); // receive specifically from Process A

Properties:

  • A link is established automatically between exactly one sender and one receiver
  • Exactly one link per pair of processes
  • Link is associated with exactly two processes — hard-coded identities
  • Changing a process name requires recompiling all sending/receiving code
  • Example: Direct socket connection between two specific processes

Indirect Communication

Processes communicate through a shared intermediary object — a mailbox (or port or message queue). The sender sends to the mailbox; the receiver reads from the mailbox.

send(Mailbox_A, message);     // send to mailbox A
receive(Mailbox_A, &message); // receive from mailbox A

Properties:

  • Two processes communicate only if they share a mailbox
  • Multiple processes can communicate through the same mailbox
  • A mailbox can be shared by many processes (one-to-many, many-to-one, many-to-many)
  • Decoupled — sender doesn't need to know the receiver's identity
  • Examples: Message queues, email systems, pub-sub systems
FeatureDirectIndirect
NamingEach process named explicitlyMailbox/queue named
CouplingTightly coupled (knows partner)Loosely coupled (via mailbox)
ScalabilityLimited (one link per pair)High (one mailbox, many users)
FlexibilityLowHigh
ExamplesDirect socket, pipeMessage queue, email

146. Role of Signals in IPC

A signal is an asynchronous notification sent to a process to inform it that a specific event has occurred. It is a lightweight, limited IPC mechanism — signals carry no data (just the signal type) and can be delivered at any time, interrupting the process's normal execution.

Common Signals

SignalNumberDefault ActionTrigger
SIGTERM15TerminatePolite termination request
SIGKILL9Terminate (cannot ignore)Force kill
SIGINT2TerminateCtrl+C
SIGSEGV11Terminate + core dumpSegmentation fault
SIGCHLD17IgnoreChild process stopped/terminated
SIGHUP1TerminateTerminal hangup / daemon reload
SIGALRM14TerminateTimer expiry
SIGUSR1/210/12TerminateUser-defined custom signal

How Signals Work

  1. A signal is sent to a process (by another process via kill(pid, sig), by the kernel, or by the process itself)
  2. The signal is delivered to the target process (usually when it next runs or is currently running)
  3. The process can:
    • Execute the default action (terminate, ignore, or core dump)
    • Run a custom signal handler function (installed with signal() or sigaction())
    • Block the signal temporarily (defer delivery)
    • Ignore the signal (except SIGKILL and SIGSTOP which cannot be ignored)

Signals as IPC

Signals provide very limited IPC — they are mainly used for:

  • Event notification — tell a daemon to reload config (SIGHUP), gracefully shut down (SIGTERM)
  • Process control — stop/resume processes (SIGSTOP/SIGCONT)
  • Error notification — kernel notifies process of faults (SIGSEGV, SIGFPE)
  • Simple coordinationSIGUSR1/SIGUSR2 for custom application events

Limitation: Signals cannot carry arbitrary data — they only convey a signal type. For data transfer, use pipes, sockets, or shared memory.


147. What is a Socket? How is it Used for Network Communication?

A socket is a communication endpoint that allows processes to exchange data — either on the same machine or across a network. It is the fundamental abstraction for network programming.

A socket is identified by:

  • IP address — identifies the machine
  • Port number — identifies the specific process/service on that machine
  • Protocol — TCP (reliable) or UDP (unreliable)

Together: (IP address, port, protocol) = socket address

Types of Sockets

Stream Socket (TCP) — connection-oriented, reliable, ordered byte stream. Uses TCP protocol. Data is guaranteed to arrive in order and without loss.

Datagram Socket (UDP) — connectionless, unreliable, unordered. Uses UDP protocol. Each packet is independent. Faster but no delivery guarantees.

Unix Domain Socket — for communication between processes on the same machine. Uses a file system path instead of IP/port. Much faster than TCP (no network stack overhead). Used by databases, X11, Docker, etc.

TCP Socket Communication Flow

Server side:                    Client side:
socket()                        socket()
bind(ip, port)
listen()
accept()  ←────────────────── connect(server_ip, port)
read()/write() ◄──────────── write()/read()
close()                         close()

Use Cases

  • Web servers — HTTP/HTTPS on port 80/443
  • Database connections — MySQL on port 3306, PostgreSQL on 5432
  • SSH — port 22
  • Email — SMTP (25), IMAP (143), POP3 (110)
  • Microservices — REST APIs, gRPC communication between services
  • Local IPC — Unix domain sockets for fast same-machine communication

Struggling to Find a Job? Get Specific Batch Wise job Updates ✅ Startup lits


JavaScript Interview Questions

Spring Boot Interview Questions

DBMS Interview Questions

Join our WhatsApp Channel for more resources.