0% found this document useful (0 votes)
5 views23 pages

OS Lab Notes

The document contains comprehensive notes on various OS lab topics including UNIX commands, shell scripting, CPU scheduling, and process/thread management. It includes detailed examples and assignments for practical understanding, covering fundamental concepts like file operations, control statements, loops, arrays, and CPU scheduling algorithms such as FCFS, SJF, and Round Robin. Each section is structured with code snippets and explanations to facilitate learning and application.

Uploaded by

aggi.kundu
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views23 pages

OS Lab Notes

The document contains comprehensive notes on various OS lab topics including UNIX commands, shell scripting, CPU scheduling, and process/thread management. It includes detailed examples and assignments for practical understanding, covering fundamental concepts like file operations, control statements, loops, arrays, and CPU scheduling algorithms such as FCFS, SJF, and Round Robin. Each section is structured with code snippets and explanations to facilitate learning and application.

Uploaded by

aggi.kundu
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

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(&notFull,&m);
buffer[in]=i; in=(in+1)%BUF; count++;
printf("Produced: %d\n",i);
pthread_cond_signal(&notEmpty);
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(&notEmpty,&m);
int item=buffer[out]; out=(out+1)%BUF; count--;
printf("Consumed: %d\n",item);
pthread_cond_signal(&notFull);
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]);
}

You might also like