OS Lab — Complete Notes
Labs 1–10 with Full Code
Shell Scripting • CPU Scheduling • Process/Thread/IPC/Synchronization
LAB 1 — UNIX Commands & Shell Scripting Basics
1.1 Common UNIX Commands
# File & Directory
ls -la # list all files with permissions
mkdir mydir # create directory
rm -rf mydir # remove directory recursively
mv file1 file2 # rename/move
cp src dst # copy
chmod 755 file # change permissions
touch [Link] # create empty file / update timestamp
cat [Link] # display file contents
basename /a/b/[Link] # → [Link]
# System Info
date # current date/time
hostname # machine name
who # logged-in users
users # list usernames
which bash # path of command
top # live process monitor
kill -9 PID # kill process
# Shell
echo "Hello" # print text
read var # read input into variable
expr 3 + 4 # arithmetic (→ 7)
bash [Link] # run script
vim file # open editor
1.2 Assignment 2 — Add Two Numbers (Command Line Arguments)
#!/bin/bash
# Usage: ./[Link] 5 3
a=$1
b=$2
sum=$(expr $a + $b)
echo "Sum = $sum"
1.3 Assignment 3 — Distance Converter
#!/bin/bash
echo -n "Enter distance in meters: "
read dist
cm=$(echo "$dist * 100" | bc)
km=$(echo "scale=3; $dist / 1000" | bc)
echo "$dist meter = $cm cm = $km km"
1.4 Assignment 4 — Date Reformatter
#!/bin/bash
# Output of 'date': Thu Jan 2 14:21:54 IST 2014
# Target format: 2/Jan/2014/14.21
d=$(date)
day=$(echo $d | awk '{print $3}') # 2
mon=$(echo $d | awk '{print $2}') # Jan
yr=$(echo $d | awk '{print $6}') # 2014
tm=$(echo $d | awk '{print $4}') # 14:21:54
hhmm=$(echo $tm | cut -d: -f1,2 | tr ':' '.') # 14.21
echo "$day/$mon/$yr/$hhmm"
# Useful date options:
date +"%d/%m/%Y" # 02/01/2014
date +"%A" # Thursday
date +"%s" # Unix timestamp
LAB 2 — Operators & Control Statements
2.1 Operators Quick Reference
# Arithmetic (use expr or $(( )))
result=$(( a + b )) # + - * / %
# Relational (inside [ ] or [[ ]])
-eq -ne -lt -le -gt -ge
# Logical
&& || ! (inside [[ ]])
-a -o (inside [ ])
# String
= != -z (empty) -n (not empty)
# File tests
-f file # is regular file
-d dir # is directory
-r/-w/-x # readable/writable/executable
2.2 Assignment 1 — Leap Year
#!/bin/bash
echo -n "Enter year: "
read y
if (( (y % 4 == 0 && y % 100 != 0) || y % 400 == 0 )); then
echo "$y is a Leap Year"
else
echo "$y is NOT a Leap Year"
fi
2.3 Assignment 2 — Greatest Among Three Numbers
#!/bin/bash
echo -n "Enter three numbers: "
read a b c
if [ $a -ge $b ] && [ $a -ge $c ]; then
echo "Greatest = $a"
elif [ $b -ge $a ] && [ $b -ge $c ]; then
echo "Greatest = $b"
else
echo "Greatest = $c"
fi
2.4 Assignment 3 — Prime Numbers 1 to 100
#!/bin/bash
echo "Prime numbers between 1 and 100:"
for (( n=2; n<=100; n++ )); do
is_prime=1
for (( i=2; i*i<=n; i++ )); do
if (( n % i == 0 )); then
is_prime=0
break
fi
done
[ $is_prime -eq 1 ] && echo -n "$n "
done
echo
2.5 Assignment 4 — ps -ef / ps -ux Filter (parent id = 2)
#!/bin/bash
# Show processes whose PPID=2, formatted as ps -ux style
ps -ux | head -1 # print header
ps -ef | awk '$3==2' # filter by PPID=2
# Alternative: print header + matching lines
ps -ux | awk 'NR==1 || $2 ~ /^[0-9]+$/' | head -1
ps -ef | awk 'NR==1{next} $3==2{print}' | while read line; do
pid=$(echo $line | awk '{print $2}')
ps -ux | awk -v p=$pid '$2==p'
done
2.6 Assignment 5 — Date in 12-Hour Format
#!/bin/bash
# 'date' → Thu Jan 2 14:21:54 IST 2014
# Target → 02/01/2014/2:21:54 PM
day=$(date +"%d")
mon=$(date +"%m")
yr=$(date +"%Y")
time12=$(date +"%I:%M:%S %p") # 12-hour with AM/PM
echo "$day/$mon/$yr/$time12"
2.7 Assignment 6 — Move Files/Dirs to MyFile/MyDir
#!/bin/bash
BASE=~/XYZ
mkdir -p $BASE/MyFile $BASE/MyDir
for item in $BASE/*; do
name=$(basename "$item")
[ "$name" = "MyFile" ] || [ "$name" = "MyDir" ] && continue
if [ -f "$item" ]; then
mv "$item" $BASE/MyFile/
elif [ -d "$item" ]; then
mv "$item" $BASE/MyDir/
fi
done
echo "Done. Files → MyFile/, Dirs → MyDir/"
LAB 3 — Loop Statements
3.1 Loop Syntax Overview
# while loop
while [ condition ]; do ... done
# until loop (opposite of while)
until [ condition ]; do ... done
# for loop (C-style)
for (( i=0; i<n; i++ )); do ... done
# for loop (list style)
for x in a b c; do ... done
# case statement
case $var in
pattern1) commands ;;
pattern2) commands ;;
*) default ;;
esac
3.2 Assignment 1 — Reverse an Integer
#!/bin/bash
echo -n "Enter integer: "
read n
rev=0
while [ $n -gt 0 ]; do
digit=$(( n % 10 ))
rev=$(( rev * 10 + digit ))
n=$(( n / 10 ))
done
echo "Reversed: $rev"
3.3 Assignment 2 — Palindrome Check
#!/bin/bash
echo -n "Enter string: "
read str
rev=$(echo $str | rev)
if [ "$str" = "$rev" ]; then
echo "'$str' is a palindrome"
else
echo "'$str' is NOT a palindrome"
fi
3.4 Assignment 3 — System Info Menu
#!/bin/bash
while true; do
echo "1. Home Directory 2. Bash Version"
echo "3. Host Name 4. Current Dir 5. Exit"
echo -n "Choose: "
read ch
case $ch in
1) echo "Home: $HOME" ;;
2) echo "Bash: $BASH_VERSION" ;;
3) echo "Host: $(hostname)" ;;
4) echo "CWD: $(pwd)" ;;
5) exit 0 ;;
*) echo "Invalid choice" ;;
esac
done
3.5 Assignment 4 — Multi-Step Arithmetic (8 args)
#!/bin/bash
# Usage: ./[Link] 12 4 7 3 ...
args=( "$@" )
result=${args[0]}
for (( i=1; i<${#args[@]} && i<8; i++ )); do
b=${args[$i]}
if (( result % b == 0 )); then
result=$(( result / b ))
echo "Divisible: result = $result / $b = $result"
elif (( result % b != 0 && b % 5 == 0 )); then
result=$(( result * b ))
echo "b%5==0: result = $result"
elif (( result > b )); then
result=$(( result - b ))
echo "a>b: result = $result"
else
result=$(( result + b ))
echo "else: result = $result"
fi
done
echo "Final result: $result"
LAB 4 — Arrays in Shell Script
4.1 Array Syntax
arr=(10 20 30 40) # declare
echo ${arr[0]} # access element → 10
echo ${#arr[@]} # length → 4
echo ${arr[@]} # all elements
arr+=(50) # append
for x in "${arr[@]}"; do echo $x; done
4.2 Assignment 1 — Concatenate Two Files Line-by-Line into Third
#!/bin/bash
# Usage: ./[Link] file1 file2 outfile
f1=$1 f2=$2 out=$3
mapfile -t lines1 < "$f1"
mapfile -t lines2 < "$f2"
len=${#lines1[@]}
[ ${#lines2[@]} -gt $len ] && len=${#lines2[@]}
> "$out"
for (( i=0; i<len; i++ )); do
echo "${lines1[$i]:-} ${lines2[$i]:-}" >> "$out"
done
echo "Result saved in $out"
cat "$out"
4.3 Assignment 2 — Split Files into Directories of Size X
#!/bin/bash
echo -n "Max files per dir (X): "
read X
files=( * )
total=${#files[@]}
dir_num=1
count=0
mkdir -p "x_$dir_num"
for f in "${files[@]}"; do
[ -d "$f" ] && continue
if [ $count -ge $X ]; then
(( dir_num++ ))
mkdir -p "x_$dir_num"
count=0
fi
cp "$f" "x_$dir_num/"
(( count++ ))
done
echo "Files distributed into x_1 ... x_$dir_num"
LAB 5 — CPU Scheduling: FCFS & SJF (Non-Preemptive)
Key Terms
Arrival Time (AT): when process enters ready queue. Burst Time (BT): CPU time needed.
Completion Time (CT): when it finishes. Turnaround Time (TAT) = CT - AT. Waiting Time (WT) =
TAT - BT.
5.1 FCFS — First Come First Served (C using struct)
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int pid, at, bt, ct, tat, wt;
} Process;
int cmpAT(const void *a, const void *b) {
return ((Process*)a)->at - ((Process*)b)->at;
}
int main() {
int n;
printf("Number of processes: "); scanf("%d", &n);
Process p[n];
for (int i=0; i<n; i++) {
p[i].pid = i+1;
printf("P%d AT BT: ", i+1);
scanf("%d %d", &p[i].at, &p[i].bt);
}
qsort(p, n, sizeof(Process), cmpAT);
int time = 0;
for (int i=0; i<n; i++) {
if (time < p[i].at) time = p[i].at;
time += p[i].bt;
p[i].ct = time;
p[i].tat = p[i].ct - p[i].at;
p[i].wt = p[i].tat - p[i].bt;
}
printf("PID\tAT\tBT\tCT\tTAT\tWT\n");
float avgWT=0, avgTAT=0;
for (int i=0; i<n; i++) {
printf("P%d\t%d\t%d\t%d\t%d\t%d\n",
p[i].pid,p[i].at,p[i].bt,p[i].ct,p[i].tat,p[i].wt);
avgWT += p[i].wt;
avgTAT += p[i].tat;
}
printf("Avg WT=%.2f Avg TAT=%.2f\n", avgWT/n, avgTAT/n);
return 0;
}
5.2 SJF Non-Preemptive (C)
#include <stdio.h>
#define MAX 10
int main() {
int pid[MAX],at[MAX],bt[MAX],ct[MAX],tat[MAX],wt[MAX];
int done[MAX]={0};
int n; printf("n: "); scanf("%d",&n);
for(int i=0;i<n;i++){
pid[i]=i+1;
printf("AT BT: "); scanf("%d %d",&at[i],&bt[i]);
}
int time=0, completed=0;
while(completed < n) {
int idx=-1, minBT=99999;
for(int i=0;i<n;i++) {
if(!done[i] && at[i]<=time && bt[i]<minBT) {
minBT=bt[i]; idx=i;
}
}
if(idx==-1){ time++; continue; }
time += bt[idx];
ct[idx]=time;
tat[idx]=ct[idx]-at[idx];
wt[idx]=tat[idx]-bt[idx];
done[idx]=1; completed++;
}
printf("PID\tAT\tBT\tCT\tTAT\tWT\n");
for(int i=0;i<n;i++)
printf("P%d\t%d\t%d\t%d\t%d\t%d\n",
pid[i],at[i],bt[i],ct[i],tat[i],wt[i]);
return 0;
}
LAB 6 — Preemptive SJF (SRTF) & Round Robin
6.1 Preemptive SJF / SRTF (C)
💡 At every time unit, pick the process with shortest REMAINING burst time.
#include <stdio.h>
#define MAX 10
int main(){
int n, at[MAX],bt[MAX],rem[MAX],ct[MAX],tat[MAX],wt[MAX],done[MAX]={0};
printf("n: "); scanf("%d",&n);
for(int i=0;i<n;i++){
printf("P%d AT BT: ",i+1); scanf("%d %d",&at[i],&bt[i]);
rem[i]=bt[i];
}
int time=0, completed=0;
while(completed<n){
int idx=-1,minR=99999;
for(int i=0;i<n;i++)
if(!done[i]&&at[i]<=time&&rem[i]<minR){minR=rem[i];idx=i;}
if(idx==-1){time++;continue;}
rem[idx]--;
time++;
if(rem[idx]==0){
ct[idx]=time;
tat[idx]=ct[idx]-at[idx];
wt[idx]=tat[idx]-bt[idx];
done[idx]=1; completed++;
}
}
printf("PID\tAT\tBT\tCT\tTAT\tWT\n");
for(int i=0;i<n;i++)
printf("P%d\t%d\t%d\t%d\t%d\t%d\n",
i+1,at[i],bt[i],ct[i],tat[i],wt[i]);
}
6.2 Round Robin (C)
💡 Each process gets a fixed time quantum. Preempted if not finished.
#include <stdio.h>
#include <string.h>
#define MAX 10
int main(){
int n,q,at[MAX],bt[MAX],rem[MAX],ct[MAX],tat[MAX],wt[MAX];
printf("n and quantum: "); scanf("%d %d",&n,&q);
for(int i=0;i<n;i++){
printf("P%d AT BT: ",i+1); scanf("%d %d",&at[i],&bt[i]);
rem[i]=bt[i];
}
int time=0, done=0;
while(done<n){
int ran=0;
for(int i=0;i<n;i++){
if(rem[i]>0 && at[i]<=time){
ran=1;
int exec = rem[i]<q ? rem[i] : q;
time += exec; rem[i] -= exec;
if(rem[i]==0){
ct[i]=time;
tat[i]=ct[i]-at[i];
wt[i]=tat[i]-bt[i];
done++;
}
}
}
if(!ran) time++;
}
printf("PID\tAT\tBT\tCT\tTAT\tWT\n");
for(int i=0;i<n;i++)
printf("P%d\t%d\t%d\t%d\t%d\t%d\n",
i+1,at[i],bt[i],ct[i],tat[i],wt[i]);
}
LAB 7 — Process Creation with fork()
fork() basics
fork() creates a child process. Returns 0 in child, child's PID in parent, -1 on error. wait(NULL) —
parent waits for ONE child. waitpid(pid, &status, 0) — wait for specific child.
7.1 Assignment 1 — Different Process Trees
Linear chain: P → C1 → C2
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(){
pid_t pid = fork();
if(pid==0){ // Child 1
printf("Child1 PID=%d\n", getpid());
pid_t pid2 = fork();
if(pid2==0){ // Child 2 (grandchild)
printf("Child2 PID=%d Parent=%d\n",getpid(),getppid());
} else {
wait(NULL);
printf("Child1 done\n");
}
} else { // Parent
wait(NULL);
printf("Parent done\n");
}
return 0;
}
Sibling tree: Parent → C1, C2
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(){
for(int i=0;i<2;i++){
pid_t pid=fork();
if(pid==0){
printf("Child%d PID=%d\n",i+1,getpid());
return 0;
}
}
wait(NULL); wait(NULL);
printf("Parent: all children done\n");
}
7.2 Assignment 2 — Parent Waits for All Children
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(){
int n=3;
for(int i=0;i<n;i++){
pid_t pid=fork();
if(pid==0){
printf("%d. Hello from child PID=%d\n",i+1,getpid());
return 0;
}
}
// Parent waits for ALL children
for(int i=0;i<n;i++){
wait(NULL);
printf("child has terminated\n");
}
printf("All children done\n");
}
LAB 8 — IPC using Pipes
Pipe basics
pipe(fd[2]) → fd[0]=read end, fd[1]=write end. dup2(fd, STDIN_FILENO) — redirect stdin to pipe.
Always close unused ends to prevent deadlock.
8.1 Assignment 1 — N-Level Message Passing (Parent → Child chain)
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define N 4
int main(){
char msg[256] = "Hello";
for(int i=0;i<N;i++){
int fd[2]; pipe(fd);
pid_t pid=fork();
if(pid==0){ // Child reads and modifies
close(fd[1]);
read(fd[0], msg, sizeof(msg));
close(fd[0]);
char suffix[20];
sprintf(suffix, "->L%d", i+1);
strcat(msg, suffix);
printf("Level %d: %s\n", i+1, msg);
// become parent for next iteration handled by loop
// (this simple version uses exec-like chaining)
return 0;
} else { // Parent writes to child
close(fd[0]);
write(fd[1], msg, strlen(msg)+1);
close(fd[1]);
wait(NULL);
break; // parent exits after one child for demo
}
}
}
8.2 Assignment 2 — Ring Topology with Pipes
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define N 4
int main(){
int fd[N][2];
for(int i=0;i<N;i++) pipe(fd[i]);
for(int i=0;i<N;i++){
pid_t pid=fork();
if(pid==0){
// read from fd[i], write to fd[(i+1)%N]
for(int j=0;j<N;j++){
if(j!=i) close(fd[j][0]);
if(j!=(i+1)%N) close(fd[j][1]);
}
char buf[256];
read(fd[i][0], buf, sizeof(buf));
printf("Process %d received: %s\n", i, buf);
char newmsg[256];
sprintf(newmsg, "%s->P%d", buf, i);
write(fd[(i+1)%N][1], newmsg, strlen(newmsg)+1);
return 0;
}
}
// Parent: close all, inject initial message
// Send initial message to process 0
char init[]="START";
write(fd[0][1], init, strlen(init)+1);
for(int i=0;i<N;i++){ close(fd[i][0]); close(fd[i][1]); }
for(int i=0;i<N;i++) wait(NULL);
}
LAB 9 — POSIX Threads (pthreads)
Compile with
gcc program.c -o out -lpthread
// Thread basics
pthread_t tid;
pthread_create(&tid, NULL, function, (void*)arg);
pthread_join(tid, NULL); // wait for thread
pthread_exit(NULL); // exit from thread
9.1 Assignment 1 — Parallel Array Sum
#include <stdio.h>
#include <pthread.h>
#define N 10
int arr[N]={1,2,3,4,5,6,7,8,9,10};
long long sum1=0, sum2=0;
void *sumFirst(void *arg){
for(int i=0;i<N/2;i++) sum1+=arr[i];
return NULL;
}
void *sumLast(void *arg){
for(int i=N/2;i<N;i++) sum2+=arr[i];
return NULL;
}
int main(){
pthread_t t1,t2;
pthread_create(&t1,NULL,sumFirst,NULL);
pthread_create(&t2,NULL,sumLast,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
printf("Total sum = %lld\n", sum1+sum2);
}
9.2 Assignment 2 — Merge Sort with Threads
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct { int *arr; int l, r; } Range;
void merge(int *a, int l, int m, int r){
int i=l,j=m+1,k=0;
int tmp[r-l+1];
while(i<=m && j<=r) tmp[k++] = a[i]<a[j] ? a[i++] : a[j++];
while(i<=m) tmp[k++]=a[i++];
while(j<=r) tmp[k++]=a[j++];
for(i=l;i<=r;i++) a[i]=tmp[i-l];
}
void *mergeSort(void *arg){
Range *rng=(Range*)arg;
int l=rng->l, r=rng->r;
if(l>=r) return NULL;
int m=(l+r)/2;
Range r1={rng->arr,l,m}, r2={rng->arr,m+1,r};
pthread_t t1,t2;
pthread_create(&t1,NULL,mergeSort,&r1);
pthread_create(&t2,NULL,mergeSort,&r2);
pthread_join(t1,NULL); pthread_join(t2,NULL);
merge(rng->arr,l,m,r);
return NULL;
}
int main(){
int a[]={5,3,8,1,9,2,7,4,6};
int n=9;
Range rng={a,0,n-1};
pthread_t t; pthread_create(&t,NULL,mergeSort,&rng);
pthread_join(t,NULL);
for(int i=0;i<n;i++) printf("%d ",a[i]);
printf("\n");
}
LAB 10 — Synchronization: Mutex, Semaphore & Classic
Problems
Compile
gcc program.c -o out -lpthread -lrt (add -lrt for semaphores on Linux)
10.1 API Quick Reference
/* MUTEX */
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&m);
pthread_mutex_unlock(&m);
/* CONDITION VARIABLE */
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
pthread_cond_wait(&cv, &m); // release lock, wait
pthread_cond_signal(&cv); // wake one
pthread_cond_broadcast(&cv); // wake all
/* SEMAPHORE (POSIX) */
#include <semaphore.h>
sem_t s;
sem_init(&s, 0, value); // 0=thread-shared
sem_wait(&s); // P() / down
sem_post(&s); // V() / up
sem_destroy(&s);
10.2 Assignment 1 — Reader-Writer Problem (Mutex)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t rw_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
int readers = 0;
int shared_data = 0;
void *reader(void *arg){
int id = *(int*)arg;
pthread_mutex_lock(&count_lock);
readers++;
if(readers==1) pthread_mutex_lock(&rw_lock); // first reader locks
pthread_mutex_unlock(&count_lock);
printf("Reader %d reads: %d\n", id, shared_data);
sleep(1);
pthread_mutex_lock(&count_lock);
readers--;
if(readers==0) pthread_mutex_unlock(&rw_lock); // last reader unlocks
pthread_mutex_unlock(&count_lock);
return NULL;
}
void *writer(void *arg){
int id = *(int*)arg;
pthread_mutex_lock(&rw_lock);
shared_data++;
printf("Writer %d writes: %d\n", id, shared_data);
sleep(1);
pthread_mutex_unlock(&rw_lock);
return NULL;
}
int main(){
pthread_t rt[3], wt[2];
int rid[]={1,2,3}, wid[]={1,2};
for(int i=0;i<3;i++) pthread_create(&rt[i],NULL,reader,&rid[i]);
for(int i=0;i<2;i++) pthread_create(&wt[i],NULL,writer,&wid[i]);
for(int i=0;i<3;i++) pthread_join(rt[i],NULL);
for(int i=0;i<2;i++) pthread_join(wt[i],NULL);
}
10.3 Assignment 2 — Critical Section using Semaphore
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
sem_t mutex;
int shared = 0;
void *increment(void *arg){
int id = *(int*)arg;
sem_wait(&mutex); // entry section
shared++; // critical section
printf("Thread %d: shared=%d\n", id, shared);
sem_post(&mutex); // exit section
return NULL;
}
int main(){
sem_init(&mutex, 0, 1); // binary semaphore
pthread_t t[5];
int ids[5]={1,2,3,4,5};
for(int i=0;i<5;i++) pthread_create(&t[i],NULL,increment,&ids[i]);
for(int i=0;i<5;i++) pthread_join(t[i],NULL);
sem_destroy(&mutex);
}
10.4 Home Assignment — Producer-Consumer (Semaphore)
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define BUF 5
int buffer[BUF], in=0, out=0;
sem_t empty, full, mutex;
void *producer(void *arg){
for(int i=1;i<=8;i++){
sem_wait(&empty);
sem_wait(&mutex);
buffer[in]=i; in=(in+1)%BUF;
printf("Produced: %d\n",i);
sem_post(&mutex);
sem_post(&full);
}
return NULL;
}
void *consumer(void *arg){
for(int i=1;i<=8;i++){
sem_wait(&full);
sem_wait(&mutex);
int item=buffer[out]; out=(out+1)%BUF;
printf("Consumed: %d\n",item);
sem_post(&mutex);
sem_post(&empty);
}
return NULL;
}
int main(){
sem_init(&empty,0,BUF);
sem_init(&full,0,0);
sem_init(&mutex,0,1);
pthread_t p,c;
pthread_create(&p,NULL,producer,NULL);
pthread_create(&c,NULL,consumer,NULL);
pthread_join(p,NULL); pthread_join(c,NULL);
sem_destroy(&empty); sem_destroy(&full); sem_destroy(&mutex);
}
10.5 Home Assignment — Producer-Consumer (Mutex + Cond Var)
#include <stdio.h>
#include <pthread.h>
#define BUF 5
int buffer[BUF], in=0, out=0, count=0;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t notFull = PTHREAD_COND_INITIALIZER;
pthread_cond_t notEmpty = PTHREAD_COND_INITIALIZER;
void *producer(void *arg){
for(int i=1;i<=8;i++){
pthread_mutex_lock(&m);
while(count==BUF) pthread_cond_wait(¬Full,&m);
buffer[in]=i; in=(in+1)%BUF; count++;
printf("Produced: %d\n",i);
pthread_cond_signal(¬Empty);
pthread_mutex_unlock(&m);
}
return NULL;
}
void *consumer(void *arg){
for(int i=1;i<=8;i++){
pthread_mutex_lock(&m);
while(count==0) pthread_cond_wait(¬Empty,&m);
int item=buffer[out]; out=(out+1)%BUF; count--;
printf("Consumed: %d\n",item);
pthread_cond_signal(¬Full);
pthread_mutex_unlock(&m);
}
return NULL;
}
int main(){
pthread_t p,c;
pthread_create(&p,NULL,producer,NULL);
pthread_create(&c,NULL,consumer,NULL);
pthread_join(p,NULL); pthread_join(c,NULL);
}
10.6 Home Assignment — Dining Philosophers (Semaphore)
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define N 5
sem_t fork_sem[N];
void *philosopher(void *arg){
int id = *(int*)arg;
int left=id, right=(id+1)%N;
// Avoid deadlock: odd picks right first
if(id%2==0){ sem_wait(&fork_sem[left]); sem_wait(&fork_sem[right]); }
else { sem_wait(&fork_sem[right]); sem_wait(&fork_sem[left]); }
printf("Philosopher %d eating\n",id);
sleep(1);
sem_post(&fork_sem[left]);
sem_post(&fork_sem[right]);
printf("Philosopher %d thinking\n",id);
return NULL;
}
int main(){
for(int i=0;i<N;i++) sem_init(&fork_sem[i],0,1);
pthread_t t[N]; int ids[N];
for(int i=0;i<N;i++){ ids[i]=i;
pthread_create(&t[i],NULL,philosopher,&ids[i]); }
for(int i=0;i<N;i++) pthread_join(t[i],NULL);
for(int i=0;i<N;i++) sem_destroy(&fork_sem[i]);
}
10.7 Home Assignment — Dining Philosophers (Mutex)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define N 5
pthread_mutex_t fork_mutex[N];
void *philosopher(void *arg){
int id = *(int*)arg;
int left=id, right=(id+1)%N;
if(id%2==0){
pthread_mutex_lock(&fork_mutex[left]);
pthread_mutex_lock(&fork_mutex[right]);
} else {
pthread_mutex_lock(&fork_mutex[right]);
pthread_mutex_lock(&fork_mutex[left]);
}
printf("Philosopher %d eating\n",id);
sleep(1);
pthread_mutex_unlock(&fork_mutex[left]);
pthread_mutex_unlock(&fork_mutex[right]);
printf("Philosopher %d thinking\n",id);
return NULL;
}
int main(){
for(int i=0;i<N;i++) pthread_mutex_init(&fork_mutex[i],NULL);
pthread_t t[N]; int ids[N];
for(int i=0;i<N;i++){ ids[i]=i;
pthread_create(&t[i],NULL,philosopher,&ids[i]); }
for(int i=0;i<N;i++) pthread_join(t[i],NULL);
for(int i=0;i<N;i++) pthread_mutex_destroy(&fork_mutex[i]);
}