Operating Systems Interview Questions and Answers
Processes, threads, scheduling, memory, deadlocks and file systems.
Whether you are preparing for entry-level Operating Systems interview questions for freshers or senior software engineer interview questions addressing concurrency, scalability, and system architecture, this track provides peer-reviewed model answers with syntax walkthroughs, edge cases, and practical interview tips.
1 What is the difference between a process and a thread? Easy
A process is a running program with its own virtual address space, code, data, heap, open file descriptors and at least one thread. The operating system isolates processes from one another, so a crash in one usually does not corrupt another.
A thread is the unit of scheduling inside a process. Threads in the same process share the address space, heap, globals and file descriptors, but each has its own stack, registers and program counter.
Process A
code + data + heap + file table
thread 1 (stack, regs) thread 2 (stack, regs)
Because threads share memory, communication is cheap but synchronisation is required; a data race can corrupt shared state. Processes are isolated, so they are safer but communicating between them needs IPC such as pipes, shared memory or sockets, which is slower and more complex. Creating a process is heavier than creating a thread, so thread pools are common for handling many concurrent requests.
2 What is the difference between user mode and kernel mode? Easy
CPUs have at least two privilege levels. In user mode, code cannot execute privileged instructions or touch hardware or protected memory. In kernel mode, the OS kernel can access devices, page tables and privileged registers.
Applications request services through system calls, the controlled entry point into the kernel: read, write, open, fork, mmap and so on. A system call switches to kernel mode, validates arguments, runs the operation and returns to user mode.
ssize_t n = read(fd, buf, size); // traps into the kernel
The boundary matters for performance: each call has overhead, so buffered I/O and batching reduce the number of transitions. It also matters for safety: a bug in user code cannot directly corrupt the kernel, and the kernel checks every pointer and permission. This separation is the foundation of process isolation and of security mechanisms such as address space layout randomisation.
3 What are the main responsibilities of an operating system? Easy
An operating system manages hardware and provides abstractions so programs do not talk to devices directly. Its main responsibilities are:
- Process management: create, schedule, suspend and terminate processes and threads, and provide synchronisation.
- Memory management: allocate memory, maintain virtual address spaces and decide what stays in RAM.
- File systems: organise persistent data into files and directories with permissions.
- Device and I/O management: provide drivers, buffering and a uniform interface to disks, network cards and peripherals.
- Security and protection: isolate processes, enforce access control and authenticate users.
- User interface and services: shells, system calls and utilities.
apps -> system calls -> kernel -> hardware
It balances competing goals: fairness and throughput in scheduling, latency versus utilisation in I/O, and safety versus performance. Examples include Linux and Windows for general use, and real-time kernels where predictable timing is the priority.
4 Compare common CPU scheduling algorithms. Medium
CPU scheduling decides which runnable thread runs next. Common policies:
- First Come First Served: simple and non-preemptive, but suffers the convoy effect when a long job blocks short ones.
- Shortest Job First: optimal average waiting time if burst lengths are known, but starvation is possible and bursts are usually guessed.
- Round Robin: each thread gets a time quantum; good response time, and the quantum trades context-switch overhead against interactivity.
- Priority: the highest priority runs; ageing prevents starvation.
- Multilevel feedback queue: multiple queues with different quanta, promoting interactive jobs and demoting CPU-bound ones.
RR with q=4: A(10) B(3) -> A4 B3 A4 A2
Real schedulers such as Linux's CFS approximate fair sharing by tracking virtual runtime rather than fixed priorities, and modern kernels also care about cache locality and NUMA. The right choice depends on whether the goal is throughput, latency or fairness.
5 Explain virtual memory and paging. Medium
Virtual memory gives each process the illusion of a large, contiguous address space, independent of physical RAM. The CPU's memory management unit translates virtual addresses to physical ones using page tables set up by the kernel.
Memory is divided into fixed-size pages, typically 4 KB, and physical memory into frames. A virtual address splits into a page number and an offset; the page table maps the page to a frame. A translation lookaside buffer caches recent translations to avoid walking the table on every access.
virtual addr = [ page number | offset ]
-> page table -> [ frame number | offset ] physical
Pages not in RAM live on disk. Accessing one triggers a page fault: the kernel loads the page, possibly evicting another. Demand paging and copy-on-write make this efficient, and the working-set model explains thrashing. Virtual memory also provides isolation, since one process cannot name another's physical frames.
6 What is a deadlock and how do you prevent it? Medium
A deadlock is a set of threads each waiting for a resource held by another, so none can proceed. Four Coffman conditions must all hold: mutual exclusion, hold and wait, no preemption, and circular wait.
Thread 1 holds A, wants B
Thread 2 holds B, wants A
Prevention breaks at least one condition. Remove mutual exclusion where possible by making resources shareable. Avoid hold and wait by requesting all resources up front. Allow preemption or rollback. Most practically, impose a global ordering on lock acquisition so a cycle cannot form.
Avoidance uses knowledge of future requests, for example the Banker's algorithm, which grants a request only if the system stays in a safe state. Detection lets deadlocks happen, builds a wait-for graph, finds a cycle and recovers by killing or rolling back a victim. Timeouts are a crude practical mitigation but risk false positives.
7 What happens during a context switch and why is it expensive? Medium
A context switch is the act of saving the state of one thread or process and restoring another so execution can resume later. The kernel saves the program counter, registers, stack pointer, status flags and any floating-point state, then loads the saved state of the next runnable entity.
If the switch is between processes rather than threads, the address space changes too, so the page tables are switched and the TLB is flushed or tagged. That makes process switches noticeably more expensive than thread switches within a process.
save regs/PC of A -> choose B -> load regs/PC of B -> resume B
Costs include direct register save and restore, cache pollution because the new workload misses previously cached data, and TLB misses. Mitigations include larger time quanta, thread pools, CPU affinity and reducing syscall frequency. Understanding this overhead explains why very small scheduling quanta hurt throughput.
8 What is the difference between a mutex and a semaphore? Medium
Both are synchronisation primitives, but they express different ideas.
A mutex provides mutual exclusion: it has an owner, it is locked or unlocked, and only the owner may unlock it. Use it to protect a critical section so only one thread at a time touches shared state.
A counting semaphore holds an integer and supports wait (decrement, block at zero) and signal (increment, wake a waiter). It has no ownership, so one thread can signal and another can wait. It is used to limit concurrency or to signal between threads.
mutex_lock(&m); balance += 10; mutex_unlock(&m);
sem_wait(&slots); /* ... */ sem_post(&slots);
A binary semaphore can act like a mutex but lacks ownership, which weakens invariant checking and priority inheritance. Prefer a mutex for locking and semaphores for signalling or resource counting. Condition variables plus a mutex are often clearer for waiting on a state change.
9 What is thrashing and how do you deal with it? Medium
Thrashing is when a system spends more time paging than doing useful work. It happens when the total working set of active processes exceeds physical memory, so pages are evicted and immediately faulted back in. CPU utilisation collapses and disk I/O saturates.
Signs include high page-fault rates, low CPU utilisation, long run queues and heavy swap activity.
Causes and fixes:
- Too many processes for the available RAM: reduce the degree of multiprogramming or add memory.
- A poor replacement policy: use a good approximation of LRU such as clock, and keep frequently reused pages resident.
- A hot loop touching more data than fits in cache or memory: improve locality of reference.
- Aggressive swapping: tune swap behaviour, though on SSDs swapping can still destroy latency.
The working-set model keeps each process's recently used pages resident and refuses to admit a process that would push the total past available frames, which is a standard admission-control remedy.
10 Implement the bounded buffer producer-consumer problem using semaphores. Medium
The bounded buffer is solved with one mutex plus two counting semaphores, empty and full.
sem_t empty, full;
pthread_mutex_t m;
buffer[N]; int head, tail;
void put(item x) {
sem_wait(&empty);
pthread_mutex_lock(&m);
buffer[tail] = x;
tail = (tail + 1) % N;
pthread_mutex_unlock(&m);
sem_post(&full);
}
void get(item *x) {
sem_wait(&full);
pthread_mutex_lock(&m);
*x = buffer[head];
head = (head + 1) % N;
pthread_mutex_unlock(&m);
sem_post(&empty);
}
empty counts free slots, full counts filled slots, and the mutex protects the buffer and indices. Signal after unlocking so a waiter does not wake and immediately block on the mutex. Initialise empty to N and full to 0. Swapping the wait order, or holding the mutex while waiting on a semaphore, risks deadlock.
11 Explain the Banker's algorithm for deadlock avoidance. Hard
The Banker's algorithm grants a resource request only if the resulting state is safe, meaning some order exists in which all processes can finish.
Inputs are the maximum claim of each process, the current allocation and the available resources. To test safety, simulate: repeatedly find a process whose remaining need is no greater than the current available vector, assume it runs to completion and releases everything, add its allocation back, and repeat. If every process can eventually finish, the order is a safe sequence.
Avail = (3,3,2)
Need = Max - Alloc
Find Need <= Avail -> run -> Avail += Alloc
If the requested allocation leaves no safe sequence, the request is denied and the process waits, even though resources are momentarily free. The costs are that processes must declare maximum needs up front, the check runs on every request, and it assumes resources are released promptly. It is mostly of theoretical interest; real systems prefer detection plus recovery.
12 How would you design a thread pool? Hard
A thread pool keeps a set of worker threads alive so tasks avoid per-request thread-creation cost. Core pieces:
- A task queue, typically bounded, holding runnable work.
- A set of workers, each looping: take a task, run it, repeat.
- A synchronisation primitive: a mutex plus condition variable, or a lock-free queue.
- Policies for core and maximum size, queue capacity, and rejection or backpressure when full.
- Lifecycle: graceful shutdown that drains the queue, plus a way to interrupt long tasks.
- Metrics: queue depth, active workers, task latency and rejection count.
submit -> [ queue ] -> worker1..workerN -> result
Sizing depends on the workload: CPU-bound pools near the core count, I/O-bound pools larger but bounded to avoid memory blow-up. Beware blocking tasks starving the pool, unbounded queues hiding overload, and thread-local state leaking between tasks. Dynamic sizing or async I/O often beats a huge fixed pool.
Frequently Asked Questions About Operating Systems Interviews
What do hiring managers evaluate in Operating Systems technical rounds?
Technical interviewers look for foundational fluency, idiomatic syntax, clarity when communicating complex logic, and awareness of performance trade-offs (e.g. memory footprint, render performance, and network latency) in production environments.
What are the best interview tips for practicing Operating Systems questions?
Use active recall: summarize each answer in your own words before revealing the model solution. Focus on explaining why a certain approach is chosen rather than just memorizing code syntax.