OS Unit 2
OS Unit 2
A process is a program in execution. It is the fundamental unit of work in an operating system (OS).
A process is different from a program, as a program is just passive code, while a process is active,
requiring CPU execution, memory, and resources.
1. What is a Process?
2. Process States
Contents of PCB:
🔹 The OS uses the PCB to manage and switch between processes efficiently.
4. Process Scheduling
5. Context Switching
When the CPU switches from one process to another, it saves the state of the current process
and loads the state of the next process.
The saved data includes registers, program counter, and PCB details.
🔹 Why is it needed?
🔹 What is IPC?
When processes need to communicate (e.g., sharing data), they use Inter-Process
Communication (IPC) mechanisms.
Types of IPC:
2. Blocking Waiting
Definition: A process suspends itself and allows the OS to put it in a waiting state until an
event occurs.
Example: A process waiting for I/O or acquiring a lock.
Impact: Saves CPU time as the process sleeps and resumes only when needed.
Usage: Used in semaphores, condition variables, and OS scheduling.
Summary
Concept Description
2. Challenges of Concurrency
A. Race Conditions
When multiple processes/threads access shared resources simultaneously, the final outcome
depends on execution order.
Example: Two threads updating a shared bank account balance might lead to incorrect results.
B. Deadlocks
When two or more processes wait indefinitely for each other to release resources.
Example: Process A locks Resource X, Process B locks Resource Y, but both need each
other’s resource to proceed.
C. Starvation
The critical section is a part of the code where shared resources are accessed.
A solution must ensure mutual exclusion, so only one process enters the critical section at a
time.
3. Principles of Concurrency
1. Mutual Exclusion
Ensures that only one process or thread can access a shared resource at a time.
Prevents race conditions and data inconsistency.
Implemented using:
o Locks (Mutex)
o Semaphores
o Monitors
2. Synchronization
A process may pause execution while waiting for I/O and another process gets CPU time.
In single-core systems, processes are executed by interleaving instructions.
In multi-core systems, processes may run in true parallelism.
The OS must schedule processes and threads efficiently to balance system performance.
Types of scheduling:
o Preemptive Scheduling – OS can interrupt a running process (e.g., Round Robin).
o Non-Preemptive Scheduling – Once a process starts, it runs until it completes or
blocks.
The OS must detect and handle deadlocks, ensuring no two processes block each other
indefinitely.
Methods:
o Deadlock Prevention – Restrict resource allocation to avoid circular waiting.
o Deadlock Detection & Recovery – Detect deadlocks and force termination if
necessary.
4. Techniques for Handling Concurrency
pthread_mutex_lock(&mutex);
// Critical Section
pthread_mutex_unlock(&mutex);
B. Semaphores
C. Monitors
High-level synchronization construct that allows only one process inside the monitor at a
time.
D. Message Passing
5. Advantages of Concurrency
6. Disadvantages of Concurrency
Summary Table
Principle Description
Mutual Exclusion Prevents multiple processes from accessing a shared resource simultaneously.
The producer-consumer problem is often implemented with a finite (bounded) buffer of size
N.
The constraints:
1. The producer must wait if the buffer is full.
2. The consumer must wait if the buffer is empty.
3. Only one process (producer or consumer) should modify the buffer at a time to
prevent race conditions.
1. Mutex (binary semaphore) – Ensures mutual exclusion while accessing the buffer.
2. Empty (counting semaphore) – Tracks empty slots in the buffer.
3. Full (counting semaphore) – Tracks filled slots in the buffer.
🔹 Consumer Process:
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
buffer[in] = item;
printf("Producer produced: %d\n", item);
in = (in + 1) % BUFFER_SIZE;
sleep(1);
}
}
sleep(2);
}
}
int main() {
pthread_t prod, cons;
pthread_join(prod, NULL);
pthread_join(cons, NULL);
sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);
return 0;
}
6. Explanation of Implementation
The producer waits if the buffer is full (sem_wait(empty)) and then inserts an item.
The consumer waits if the buffer is empty (sem_wait(full)) before consuming an item.
pthread_mutex_lock(&mutex) ensures that only one thread accesses the buffer at a time.
Semaphores (empty and full) track the availability of buffer slots.
7. Alternative Solutions
Blocking Operations sem_wait() (wait) and sem_post() (signal) prevent race conditions.
Conclusion
A critical section is a part of the program where shared resources (e.g., files, memory, database) are
accessed.
The critical section problem arises when multiple processes attempt to execute their critical sections
simultaneously, leading to data corruption or unexpected behavior.
// Process P1
balance = balance + 100;
// Process P2
balance = balance - 50;
If P1 and P2 execute simultaneously, the final balance may be incorrect due to inconsistent updates.
The goal of mutual exclusion is to prevent such conflicts by ensuring only one process modifies
balance at a time.
1. Mutual Exclusion:
o Only one process can be inside the critical section at a time.
2. Progress:
o If no process is in the critical section, other processes should not be unnecessarily
delayed.
3. Bounded Waiting (Fairness):
o A process waiting for access should eventually enter the critical section (avoids
starvation).
4. No Assumptions About CPU Speed or Number of Processors:
o The solution should work regardless of hardware specifications.
A) Software-Based Solutions
These solutions rely on algorithms that do not require special hardware support.
// Process i
flag[i] = true;
turn = j;
while (flag[j] && turn == j); // Wait if other process wants to enter
// Critical Section
1. Disabling Interrupts
A process disables CPU interrupts before entering the critical section and enables them
afterward.
Drawback:
o Works in single-core systems but fails in multi-core CPUs since other cores can still
execute processes.
Uses an atomic hardware instruction to check and update a shared lock variable.
Example:
wait(mutex); // Lock
// Critical Section
signal(mutex); // Unlock
Types of Semaphores:
o Binary Semaphore (Mutex Lock): 0 or 1 value (like a lock).
o Counting Semaphore: Allows multiple processes (e.g., resource pools).
A mutex (mutual exclusion lock) is a special binary semaphore used for exclusive access.
A) Race Condition
Occurs when multiple processes read and write shared data simultaneously, leading to
inconsistent results.
Solution: Use synchronization mechanisms like mutexes or semaphores.
B) Deadlocks
Occurs when two or more processes wait indefinitely for resources held by each other.
Example: Process A waits for Resource X, while Process B waits for Resource Y, but both
resources are locked.
Solution:
o Avoid circular wait conditions.
o Use deadlock prevention techniques (e.g., priority allocation).
C) Starvation
Occurs when a low-priority process never gets access because higher-priority processes keep
executing.
Solution:
o Use Fair Scheduling (FIFO queues).
o Apply priority aging (increase process priority over time).
Test & Set Lock Works for multiple processes Causes busy waiting
Conclusion
Mutual exclusion is essential for concurrent programming to avoid race conditions and
ensure data integrity.
Different techniques (software, hardware, OS-level) are used based on system requirements.
Choosing the right synchronization method depends on system constraints like
performance, fairness, and resource availability.
The critical section is the part of a program where a process accesses shared resources
(variables, files, memory, etc.).
The Critical Section Problem arises when multiple processes try to access shared resources
simultaneously, leading to race conditions and data inconsistency.
The goal is to ensure only one process executes in the critical section at a time (Mutual
Exclusion).
1. Mutual Exclusion
o Only one process can be inside the critical section at a time.
2. Progress
o If no process is in the critical section, then other processes must not be blocked from
entering.
3. Bounded Waiting
o A process must enter the critical section within a finite time (avoiding starvation).
3. Solution Approaches
A. Software-Based Solutions
1. Peterson’s Algorithm
o Works for two processes using two shared variables:
flag[i] = true (indicates process wants to enter).
turn = j (gives priority to one process at a time).
do {
flag[i] = true;
turn = j;
while (flag[j] && turn == j); // Wait if other process is in CS
// Critical Section
2. Dekker’s Algorithm
o Similar to Peterson’s but ensures mutual exclusion using a turn variable.
B. Hardware-Based Solutions
1. Disable Interrupts
o A process disables CPU interrupts before entering the critical section and enables
them after leaving.
o Issues: Not suitable for multiprocessor systems.
2. Test-and-Set (Atomic Instruction)
o Uses a hardware-supported atomic instruction to check and set a lock.
do {
while (TestAndSet(lock)); // Busy waiting
// Critical Section
1. Semaphores
o A binary semaphore (mutex) ensures only one process enters the critical section at a
time.
sem_wait(mutex);
// Critical Section
sem_post(mutex);
2. Mutex Locks
o Simple lock/unlock mechanism.
c
CopyEdit
pthread_mutex_lock(&mutex);
// Critical Section
pthread_mutex_unlock(&mutex);
3. Monitors
o High-level synchronization, where only one process can access the monitor’s critical
section.
Deadlock: Occurs when two or more processes wait indefinitely for each other.
Starvation: A low-priority process may never get a chance to enter the critical section.
Solution:
5. Summary Table
Approach Description
Conclusion
The critical section problem is key to concurrent programming and operating system
synchronization.
Semaphores, mutexes, and monitors are widely used to ensure safe access to shared
resources.
Dekker’s algorithm is the first known software-based solution to the critical section
problem.
It ensures mutual exclusion for two processes without using special hardware instructions.
Uses two flags (to indicate interest in entering the critical section) and a turn variable (to
decide which process gets priority).
#define NUM_ITERATIONS 5
// Critical Section
printf("Process 0 in critical section\n");
sleep(1);
// Exit Section
turn = 1;
flag[0] = false;
}
return NULL;
}
// Critical Section
printf("Process 1 in critical section\n");
sleep(1);
// Exit Section
turn = 0;
flag[1] = false;
}
return NULL;
}
int main() {
pthread_t t0, t1;
return 0;
}
4. Explanation of Code
Each process sets its flag to true before entering the critical section.
If both processes want to enter, the turn variable determines who goes first.
The waiting process repeatedly checks turn until it gets access.
After exiting, the process gives turn to the other process and sets its flag to false.
Concept Uses flag array and turn variable Uses flag array and turn variable
Suitability Works for two processes only Works for two processes only
Implementation Complex but works on all hardware Simpler but requires hardware support
7. Summary
Dekker’s algorithm is a software-based solution to the critical section problem for two
processes.
It ensures mutual exclusion, progress, and bounded waiting using two flags and a turn
variable.
It has been replaced by modern synchronization primitives like mutexes, semaphores,
and monitors.
Peterson’s Algorithm for the Critical Section Problem
1. What is Peterson’s Algorithm?
1. Mutual Exclusion – Only one process can enter the critical section at a time.
2. Progress – If one process wants to enter, it must be allowed if no other process is in the
critical section.
3. Bounded Waiting – No process waits indefinitely to enter the critical section.
#define NUM_ITERATIONS 5
// Critical Section
printf("Process 0 in critical section\n");
sleep(1);
// Exit Section
flag[0] = false;
}
return NULL;
}
// Critical Section
printf("Process 1 in critical section\n");
sleep(1);
// Exit Section
flag[1] = false;
}
return NULL;
}
int main() {
pthread_t t0, t1;
pthread_join(t0, NULL);
pthread_join(t1, NULL);
return 0;
}
4. Explanation of Code
1. Entry Section:
o Each process sets its flag to true to indicate it wants to enter.
o It sets turn to the other process, allowing it to proceed if it also wants to enter.
o If the other process already has the turn and wants to enter, it waits.
2. Critical Section:
o The process performs its operations safely without interference.
3. Exit Section:
o The process resets its flag to false, allowing the other process to enter.
Suitability Works for two processes only Works for two processes only
Feature Peterson’s Algorithm Dekker’s Algorithm
7. Summary
2. Types of Semaphores
3. Operations on Semaphores
P(S):
while (S ≤ 0) wait; // Wait if resource is unavailable
S = S - 1; // Acquire the resource
V(S):
S = S + 1; // Release the resource
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
int main() {
pthread_t t1, t2;
pthread_join(t1, NULL);
pthread_join(t2, NULL);
sem_destroy(&semaphore); // Clean up
return 0;
}
void enter_critical_section() {
while (TestAndSet(&lock)); // Busy-wait until lock is free
}
void exit_critical_section() {
lock = false; // Release the lock
}
Atomicity Ensures that read and write occur as a single, unbreakable step.
Busy Waiting If the lock is held, other processes continuously check, leading to CPU wastage.
Mutual Exclusion Only one process can enter the critical section at a time.
❌ Leads to Busy Waiting (Spinlock) – Wastes CPU cycles if waiting processes keep checking.
❌ Can cause Starvation – Some processes might never get the lock if others keep acquiring it.
✅ Solution – Use Test and Set with Backoff or use more advanced techniques like Mutexes and
Semaphores.
🔴 Deadlock: All philosophers pick up their left fork and wait for the right fork, leading to an infinite
wait.
🟡 Starvation: Some philosophers might never get to eat if others keep eating continuously.
while (1) {
printf("Philosopher %d is thinking...\n", id);
sleep(1);
// Eating
printf("Philosopher %d is eating...\n", id);
sleep(2);
// Release forks
sem_post(&forks[id]);
sem_post(&forks[(id + 1) % N]);
int main() {
pthread_t philosophers[N];
int ids[N];
return 0;
}
✅ Solution avoids deadlock by ensuring that forks are always picked up in a fixed order.
1. Even philosophers pick the right fork first, then the left.
2. Odd philosophers pick the left fork first, then the right.
✅ This prevents circular wait, avoiding deadlock.
A butler (or coordinator) ensures that only (N-1) philosophers attempt to eat at a time.
If a philosopher wants to eat, they must ask the butler for permission.
✅ Prevents deadlock and starvation.
5. Summary Table
Deadlock- Starvation-
Solution Complexity
Free? Free?
Scenario:
2. Challenges
C Implementation
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
int main() {
pthread_t barber_thread, customer_threads[10];
// Initialize semaphores
sem_init(&customers, 0, 0);
sem_init(&barber, 0, 0);
sem_init(&mutex, 0, 1);
return 0;
}
4. Explanation of Solution
1. Customers arrive:
o If there is a seat, they wait.
o If no seat is available, they leave.
2. Barber sleeps when no customers:
o The barber waits for a customer to arrive.
3. When a customer is present:
o The barber wakes up and starts cutting hair.
4. Mutual exclusion (mutex) ensures safe access to
the waiting count.
6. Summary Table
Feature Description
2. IPC Models
✅ Advantages:
❌ Disadvantages:
Processes communicate by sending and receiving messages via the operating system.
Does not require shared memory.
Can be synchronous (blocking) or asynchronous (non-blocking).
✅ Advantages:
❌ Disadvantages:
🔹 Example:
(4) Semaphores
(5) Sockets
High-Speed Local
Shared Memory Bidirectional Yes
Communication
5. Summary
🔹 Example:
#include <stdio.h>
#include <unistd.h>
int main() {
int pid = fork();
if (pid == 0)
printf("Child process: PID = %d\n", getpid());
else
printf("Parent process: PID = %d\n", getpid());
return 0;
}
🔹 Example:
#include <stdio.h>
#include <unistd.h>
int main() {
execl("/bin/ls", "ls", "-l", NULL);
return 0;
}
🔹 Example:
5. Process Termination
6. Summary Table
Method Function