Loading W Code...
Top questions asked at FAANG & product companies
Process: • Independent program in execution with own memory space • Has own address space, code, data, heap, stack • Communication via IPC (pipes, sockets, shared memory) • Context switching is expensive • One process crash doesn't affect others
Thread: • Lightweight unit of execution within a process • Shares memory with other threads of same process • Communication via shared memory (direct) • Context switching is cheap • One thread crash can crash entire process
Key Point: Threads share heap but have separate stacks.
FCFS (First Come First Serve) • Non-preemptive, simple, causes convoy effect
SJF (Shortest Job First) • Non-preemptive, optimal average waiting time • Can cause starvation
SRTF (Shortest Remaining Time First) • Preemptive SJF, even better waiting time
Round Robin • Preemptive, time quantum based • Good for time-sharing systems • No starvation
Priority Scheduling • Based on priority, can cause starvation • Solution: Aging
Best for interviews: Know Round Robin, Priority, and their trade-offs.
All 4 conditions must hold simultaneously:
Mutual Exclusion • At least one resource must be non-sharable • Only one process can use at a time
Hold and Wait • Process holding resources can request more
No Preemption • Resources can't be forcibly taken
Circular Wait • P1 → P2 → P3 → P1 (circular chain)
How to Prevent: • Break Mutual Exclusion: Use sharable resources • Break Hold & Wait: Request all at once • Break No Preemption: Allow resource preemption • Break Circular Wait: Order resources, request in order
Virtual Memory: Technique that allows execution of processes larger than physical memory.
How it works:
Key Components: • Page Table: Maps virtual to physical addresses • TLB: Cache for page table entries • Swap Space: Disk area for swapped pages
Page Fault:
Benefits: • Run programs larger than RAM • Better memory utilization • Process isolation
Paging: • Divides memory into fixed-size pages/frames • Eliminates external fragmentation • May have internal fragmentation • Invisible to programmer • 1D address (page + offset)
Segmentation: • Divides memory into variable-size segments • Based on logical divisions (code, data, stack) • Has external fragmentation • Visible to programmer • 2D address (segment + offset)
Comparison:
| Aspect | Paging | Segmentation |
|---|---|---|
| Size | Fixed | Variable |
| Fragmentation | Internal | External |
| Programmer View | No | Yes |
| Sharing | Hard | Easy |
Modern OS: Use both (segmented paging)
Thrashing: System spends more time paging than executing useful work.
Cause: • Too many processes • Each gets fewer frames than needed • Constant page faults • CPU utilization drops • OS adds more processes (makes it worse!)
Signs: • High page fault rate • Low CPU utilization • High disk I/O
Prevention:
Working Set Model • Give each process enough frames for its working set
Page Fault Frequency • Monitor fault rate • Add frames if too high • Remove if too low
Reduce multiprogramming • Suspend some processes
Local replacement • Process only replaces its own pages
Semaphore: Integer variable for process synchronization.
Operations: • wait(S) / P(S): Decrement, block if < 0 • signal(S) / V(S): Increment, wake waiting process
Types:
Binary Semaphore (Mutex) • Value: 0 or 1 • Used for mutual exclusion
Counting Semaphore • Value: 0 to N • Used for resource counting
Example - Producer Consumer:
empty = N, full = 0, mutex = 1
Producer:
wait(empty)
wait(mutex)
// add item
signal(mutex)
signal(full)
Consumer:
wait(full)
wait(mutex)
// remove item
signal(mutex)
signal(empty)
Context Switch: Saving state of current process and loading state of another process.
When does it happen? • Time slice expires (preemption) • Process makes blocking system call • Higher priority process arrives • Interrupt occurs
What is saved (PCB): • Program counter • CPU registers • Memory management info • I/O status • Scheduling info
Time Taken: • Typically 1-1000 microseconds • Pure overhead (no useful work)
Why Thread Switch is Faster: • Threads share address space • No need to switch memory mappings • Only save/restore registers
Optimization: • Minimize context switches • Use user-level threads • Efficient scheduling algorithms
When all frames are full, which page to replace?
FIFO (First In First Out) • Replace oldest page • Simple but has Belady's Anomaly
Optimal (OPT) • Replace page not used for longest future time • Best but impractical (needs future knowledge)
LRU (Least Recently Used) • Replace page not used for longest past time • Good approximation of OPT • Implementation: Counter or Stack
Clock (Second Chance) • Circular queue with reference bit • If R=0: replace, If R=1: clear R, move on
Performance: OPT > LRU > Clock ≈ FIFO
Important: LRU is most commonly asked!
Race Condition: When outcome depends on the order of execution of concurrent processes accessing shared data.
Example:
counter = 5
P1: counter++ (read 5, increment, write 6)
P2: counter-- (read 5, decrement, write 4)
If interleaved:
P1 reads 5
P2 reads 5
P1 writes 6
P2 writes 4 ← Wrong! Should be 5
Solutions:
Mutex/Locks • Only one process in critical section
Semaphores • More flexible than mutex
Monitors • High-level synchronization
Atomic Operations • Hardware support for atomicity
Key: Always protect shared resources with synchronization primitives!
Mutex (Mutual Exclusion): • Binary (0 or 1) • Owned by the locking thread • Only owner can unlock • Used for mutual exclusion
Semaphore: • Can be any non-negative integer • Not owned by any thread • Any thread can signal • Used for signaling and resource counting
Key Differences:
| Aspect | Mutex | Semaphore |
|---|---|---|
| Value | 0 or 1 | 0 to N |
| Ownership | Yes | No |
| Unlock | Only owner | Anyone |
| Purpose | Mutual exclusion | Signaling |
When to use: • Mutex: Protecting critical section • Semaphore: Producer-consumer, resource pool
User Mode: • Limited privileges • Can't directly access hardware • Can't execute privileged instructions • Application code runs here • If crash, only that process affected
Kernel Mode: • Full privileges • Direct hardware access • Can execute any instruction • OS kernel runs here • If crash, system crash
Mode Switch (Trap):
User Mode
│
│ System Call / Interrupt
▼
Kernel Mode
│
│ Return
▼
User Mode
Why Two Modes? • Protection: Prevent user programs from:
• Stability: Faulty user program can't crash OS
System Call: Interface between user programs and OS kernel.
Process:
Categories & Examples: • Process Control: fork(), exec(), exit(), wait() • File Management: open(), read(), write(), close() • Device Management: ioctl(), read(), write() • Information: getpid(), alarm(), sleep() • Communication: pipe(), shmget(), mmap()
Example - Reading a file:
fd = open("file.txt", O_RDONLY); // System call
read(fd, buffer, 100); // System call
close(fd); // System call
Belady's Anomaly: Counter-intuitive situation where increasing page frames causes MORE page faults.
Occurs with: FIFO page replacement
Example: Reference String: 1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5
3 frames: 9 page faults 4 frames: 10 page faults (MORE!)
Why FIFO causes this: • FIFO doesn't consider page usage frequency • Oldest page might still be needed • More frames can evict useful pages
Algorithms that DON'T have this: • LRU (Least Recently Used) • Optimal (OPT) • Stack-based algorithms
Interview Tip: Know this is specific to FIFO!
Non-Preemptive: • Process runs until it terminates or blocks • CPU cannot be taken away forcefully • Simple to implement • Can cause starvation • Examples: FCFS, SJF
Preemptive: • CPU can be taken from running process • Based on priority or time quantum • Better response time • More context switches (overhead) • Examples: Round Robin, SRTF, Priority
Comparison:
| Aspect | Non-Preemptive | Preemptive |
|---|---|---|
| CPU taken | No | Yes |
| Context Switch | Less | More |
| Response Time | Poor | Good |
| Implementation | Simple | Complex |
| Use Case | Batch | Interactive |
File System: Method to store, organize, and retrieve data on storage devices.
Key Components: • Files: Named collection of related data • Directories: Container for files and other directories • Metadata: Info about files (size, permissions, timestamps)
File Allocation Methods:
Contiguous Allocation • Files stored in consecutive blocks • Fast sequential access • External fragmentation problem
Linked Allocation • Each block points to next • No external fragmentation • Slow random access
Indexed Allocation (Most Common) • Index block contains pointers to all file blocks • Support for random access • Example: Unix inode
inode Structure (Unix):
• File type, permissions
• Owner, group
• Size, timestamps
• Direct pointers (12)
• Single indirect pointer
• Double indirect pointer
• Triple indirect pointer
Disk Scheduling: Deciding order to service disk I/O requests.
Key Term: • Seek Time: Time to move disk arm to track
Algorithms:
FCFS (First Come First Serve) • Simple, fair • Can cause zig-zag arm movement
SSTF (Shortest Seek Time First) • Choose nearest request • Better than FCFS • Can cause starvation
SCAN (Elevator Algorithm) • Move in one direction, service all • Reverse at end • More uniform wait time
C-SCAN (Circular SCAN) • Like SCAN but jumps to start • More uniform response time
LOOK / C-LOOK • Like SCAN/C-SCAN but reverses at last request • Doesn't go to end of disk
Comparison:
| Algorithm | Throughput | Response | Starvation |
|---|---|---|---|
| FCFS | Low | Variable | No |
| SSTF | High | Fast | Yes |
| SCAN | High | Medium | No |
| C-SCAN | High | Uniform | No |
fork(): System call to create a new process (child) that is a copy of the calling process (parent).
What happens:
Return Values: • Parent: Gets child's PID (positive) • Child: Gets 0 • Error: Returns -1
#include <unistd.h>
#include <stdio.h>
int main() {
int pid = fork();
if (pid == 0) {
// Child process
printf("I am child, my PID: %d\n", getpid());
} else if (pid > 0) {
// Parent process
printf("I am parent, child PID: %d\n", pid);
} else {
// Error
printf("Fork failed!\n");
}
return 0;
}
Copy-on-Write (COW): • Initially parent and child share pages • Only copy when either writes • Optimization to avoid copying everything
Zombie Process: • Child has terminated but parent hasn't called wait() • Takes up entry in process table • Also called "defunct" process • Can't be killed (already dead!)
How it happens:
Child finishes → sends SIGCHLD to parent
Parent doesn't call wait() → child becomes zombie
Fix: • Parent calls wait() or waitpid() • If parent dies, init (PID 1) adopts and cleans
Orphan Process: • Child is running but parent has terminated • Adopted by init process (PID 1) • Not a problem - just re-parented
Comparison:
| Type | Parent | Child | Problem? |
|---|---|---|---|
| Zombie | Running | Dead | Yes - uses resources |
| Orphan | Dead | Running | No - adopted by init |
Prevention: • Always call wait() for child processes • Use signal handler for SIGCHLD • Double fork technique
Starvation: • Process waits indefinitely for resources • Resources ARE available, just not given • Other processes keep getting priority • Process is technically runnable
Causes: • Priority scheduling without aging • Unfair resource allocation • Continuous stream of high-priority processes
Deadlock: • Processes wait forever in circular dependency • Resources NOT available (held by waiting processes) • Involves 2+ processes • No progress possible for anyone
Key Differences:
| Aspect | Starvation | Deadlock |
|---|---|---|
| Resources | Available | Not available |
| Processes | One can be affected | 2+ always |
| Progress | Others make progress | No one progresses |
| Cause | Unfair scheduling | Circular wait |
| Solution | Aging | Prevention/Detection |
Solutions:
Starvation: • Aging: Increase priority over time • Fair scheduling (Round Robin)
Deadlock: • Prevention (break one condition) • Avoidance (Banker's algorithm) • Detection & Recovery