Lab Second OS
Lab Second OS
Theory: C program uses fork() to create a child process. exit() is called to terminate the child
process. wait() is used by the parent to wait for the child to finish, ensuring proper
synchronization. (getpid(), getppid()): These functions fetch the current process ID and the
parent process ID, which help visualize how the parent and child relate.
GCC (GNU Compiler Collection): Compiles .c file into an executable.
Linux Terminal: Runs commands like gcc, executes program, and displays output.
VS Code: Used for writing and editing C code.
Remote SSH Extension (VS Code): Lets you connect to Ubuntu VM and write code directly
into it.
Ubuntu VM (via VirtualBox or UTM): Linux environment for compiling and running the code.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
if (pid < 0)
{
perror("Fork failed");
exit(1);
}
else if (pid == 0)
{
// Child process
printf("\n--- Child Process ---\n");
printf("Child PID: %d\n", getpid());
printf("Parent PID: %d\n", getppid());
printf("Child is terminating now.\n");
exit(0);
}
else
{
// Parent process
printf("\n--- Parent Process ---\n");
printf("Parent PID: %d\n", getpid());
printf("Created Child PID: %d\n", pid);
printf("Parent is waiting for child to terminate...\n");
wait(NULL); // Wait for child
printf("Child terminated. Parent ends.\n");
}
printf("\nLab No.: 2\nName: Anjali Rai\nRoll No./Section: 02/A\n");
return 0;
}
Output:
Theory: C program uses pthread_create() to spawn a new thread that runs concurrently with
the main thread. pthread_exit() is used to terminate the thread gracefully. pthread_join()
ensures the main thread waits for the created thread to finish, achieving proper
synchronization. pthread_self() fetches the thread ID, helping to distinguish between threads.
GCC (GNU Compiler Collection): Compiles .c file into an executable using the -pthread flag
to enable POSIX threading support.
Linux Terminal: Runs compilation (gcc) and execution commands (./thread_demo), and
displays output for both main and thread execution.
VS Code: Used for writing and editing the C code.
Remote SSH Extension (VS Code): Allows you to connect to your Ubuntu virtual machine
and directly write/run code inside it from your host machine.
Ubuntu VM (via VirtualBox or UTM): Linux environment used to compile and run the multi-
threaded C program.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int main() {
pthread_t thread;
Output:
4.a) WAP to simulate the solution producer consumer problem using semaphore.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define SIZE 5
int buffer[SIZE];
int in = 0, out = 0;
sem_t empty;
sem_t full;
pthread_mutex_t mutex;
buffer[in] = item;
printf("Producer produced: %d at index %d\n", item, in);
in = (in + 1) % SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
sleep(1);
}
pthread_exit(NULL);
}
item = buffer[out];
printf("Consumer consumed: %d from index %d\n", item, out);
out = (out + 1) % SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL) {
printf("Running from: %s\n\n", path);
} else {
perror("getcwd() error");
}
pthread_t prod, cons;
sem_init(&empty, 0, SIZE);
sem_init(&full, 0, 0);
pthread_mutex_init(&mutex, NULL);
pthread_join(prod, NULL);
pthread_join(cons, NULL);
sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <limits.h>
#include <semaphore.h>
#define NUM 5
#define ROUNDS 3
sem_t forks[NUM];
sem_t room;
sem_wait(&room);
sem_wait(&forks[id]);
sem_wait(&forks[(id + 1) % NUM]);
sem_post(&forks[(id + 1) % NUM]);
sem_post(&forks[id]);
sem_post(&room);
}
pthread_exit(NULL);
}
int main()
{
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL)
{
printf("Running from: %s\n\n", path);
}
else
{
perror("getcwd() error");
}
pthread_t threads[NUM];
sem_destroy(&room);
return 0;
}
Output:
4.c) WAP to simulate the solution of producer consumer problem using message
passing technique.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <unistd.h>
#define SIZE 5
#define ITEMS 10
int buffer[SIZE];
int in = 0, out = 0, count = 0;
buffer[in] = i;
printf("Producer: Produced item %d at buffer[%d]\n", i, in);
in = (in + 1) % SIZE;
count++;
pthread_cond_signal(¬_empty);
pthread_mutex_unlock(&lock);
}
pthread_exit(NULL);
}
int main() {
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL) {
printf("Running from: %s\n\n", path);
} else {
perror("getcwd() error");
}
pthread_t prod, cons;
printf("Simulation of Producer-Consumer using Message Passing (Condition
Variables)\n\n");
pthread_create(&prod, NULL, producer, NULL);
pthread_create(&cons, NULL, consumer, NULL);
pthread_join(prod, NULL);
pthread_join(cons, NULL);
printf("\nExecution completed.\n");
printf("\nLab No.: 4.c)\nName: Anjali Rai\nRoll No./Section: 02/A\n");
return 0;
}
Output:
Code:
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
int main()
{
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL)
{
printf("Running from: %s\n\n", path);
}
else
{
perror("getcwd() error");
}
int n, i, j;
printf("Enter number of processes to schedule: ");
scanf("%d", &n);
// Swap arrival
int tmp = arrival[i];
arrival[i] = arrival[pos];
arrival[pos] = tmp;
// Swap burst
tmp = burst[i];
burst[i] = burst[pos];
burst[pos] = tmp;
// Swap index
tmp = index[i];
index[i] = index[pos];
index[pos] = tmp;
}
time += burst[i];
completion[i] = time;
turnaround[i] = completion[i] - arrival[i];
waiting[i] = turnaround[i] - burst[i];
}
// Print Table
printf("\nPID\tAT\tBT\tCT\tTAT\tWT\n");
double total_tat = 0, total_wt = 0;
for (i = 0; i < n; i++)
{
printf("P%d\t%d\t%d\t%d\t%d\t%d\n",
index[i], arrival[i], burst[i], completion[i], turnaround[i], waiting[i]);
total_tat += turnaround[i];
total_wt += waiting[i];
}
return 0;
}
Output:
5.b) WAP to simulate SJF CPU Scheduling Algorithm
Theory: C program simulates Shortest Job First (SJF) Non-Preemptive CPU scheduling
using arrays and loops to manage process data.
getcwd() from <unistd.h> and <limits.h> is used to display the current working directory
before execution.
User inputs arrival time and burst time for each process, which are stored in arrays.
The program uses selection logic to choose the process with the shortest burst time among
those that have already arrived (at[i] <= time) and are not yet completed.
Code:
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
int main() {
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL)
{
printf("Running from: %s\n\n", path);
}
else
{
perror("getcwd() error");
}
int n, i, time = 0, smallest;
int at[10], bt[10], ct[10], tat[10], wt[10], index[10];
int original_bt[10];
float total_tat = 0, total_wt = 0;
int completed = 0;
printf("\nGantt Chart:\n|");
while (completed < n) {
smallest = -1;
if (smallest == -1) {
time++;
continue;
}
time += bt[smallest];
ct[smallest] = time;
tat[smallest] = ct[smallest] - at[smallest];
wt[smallest] = tat[smallest] - original_bt[smallest];
total_tat += tat[smallest];
total_wt += wt[smallest];
// Time line
printf("\n0");
time = 0;
completed = 0;
while (completed < n) {
smallest = -1;
for (i = 0; i < n; i++) {
if (at[i] <= time && original_bt[i] > 0) {
if (bt[i] == 0 && ct[i] > time)
smallest = i;
}
}
if (smallest != -1) {
time = ct[smallest];
printf(" %d", time);
completed++;
} else {
time++;
}
}
// Output table
printf("\n\nPID\tAT\tBT\tCT\tTAT\tWT\n");
for (i = 0; i < n; i++) {
printf("P%d\t%d\t%d\t%d\t%d\t%d\n", i + 1, at[i], original_bt[i], ct[i], tat[i], wt[i]);
}
return 0;
}
Output:
5.c) WAP to simulate SRTF CPU Scheduling Algorithm.
Theory: C program implements Shortest Job First (SJF) Preemptive scheduling (also called
Shortest Remaining Time First).
getcwd() from <unistd.h> and <limits.h> is used to display the current working directory
before execution starts.
User inputs arrival time and burst time for each process, stored in arrays.
The program simulates CPU scheduling time unit by time unit, selecting the process with the
shortest remaining burst time that has already arrived.
Process execution is tracked per time unit, decrementing the burst time of the chosen process.
Code:
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
int main() {
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL) {
printf("Running from: %s\n\n", path);
} else {
perror("getcwd() error");
}
int a[10], b[10], x[10];
int waiting[10], turnaround[10], completion[10];
int i, smallest, count = 0, time = 0, n;
float avg = 0, tt = 0;
if (smallest == -1) {
time++;
continue;
}
b[smallest]--;
if (last_proc != smallest) {
gantt_proc[gantt_len] = smallest;
gantt_time[gantt_len] = time;
gantt_len++;
last_proc = smallest;
}
if (b[smallest] == 0) {
count++;
completion[smallest] = time + 1;
turnaround[smallest] = completion[smallest] - a[smallest];
waiting[smallest] = turnaround[smallest] - x[smallest];
avg += waiting[smallest];
tt += turnaround[smallest];
}
time++;
}
gantt_time[gantt_len] = time;
printf("\n\nGantt Chart:\n");
for (i = 0; i < gantt_len; i++) {
printf("| P%d ", gantt_proc[i] + 1);
}
printf("|\n");
printf("\nPID\tAT\tBT\tCT\tTAT\tWT\n");
for (i = 0; i < n; i++) {
printf("P%d\t%d\t%d\t%d\t%d\t%d\n", i + 1, a[i], x[i], completion[i], turnaround[i],
waiting[i]);
}
return 0;
}
Output:
Theory: This C program simulates the Round Robin CPU scheduling algorithm, where each
process is assigned a fixed time quantum and executed in a circular order. It uses arrays to
store arrival time, burst time, and remaining time for up to 10 processes, and implements
logic to calculate turnaround time, waiting time, and generate a Gantt chart showing the
execution sequence. The program uses standard C libraries (stdio.h, unistd.h, limits.h) for
input/output and retrieving the current working directory. It calculates and displays average
waiting and turnaround times, and uses conditionals and loops to control the scheduling flow,
while ensuring synchronization of process arrival with CPU availability.
Code:
#include<stdio.h>
#include <unistd.h>
#include <limits.h>
int main() {
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL) {
printf("Running from: %s\n\n", path);
} else {
perror("getcwd() error");
}
int cnt, j, n, t, remain, flag = 0, tq;
int wt = 0, tat = 0, at[10], bt[10], rt[10];
int gantt_process[100], gantt_start[100], gantt_end[100], gidx = 0;
rt[cnt] = 0;
flag = 1;
} else if (rt[cnt] > 0) {
gantt_start[gidx] = t;
rt[cnt] -= tq;
t += tq;
gantt_end[gidx] = t;
gantt_process[gidx] = cnt + 1;
gidx++;
}
if (cnt == n - 1)
cnt = 0;
else if (at[cnt + 1] <= t)
cnt++;
else
cnt = 0;
}
printf("\nGantt Chart:\n");
for (int i = 0; i < gidx; i++) {
printf("| P%d ", gantt_process[i]);
}
printf("|\n");
printf("0");
for (int i = 0; i < gidx; i++) {
printf("%6d", gantt_end[i]);
}
printf("\n");
printf("\nLab No.: 5.d)\nName: Anjali Rai\nRoll No./Section: 02/A\n");
return 0;
}
Output:
5.e) WAP to simulate Non-Preemptive Priority Scheduling Algorithm
Theory: This C program implements the Non-Preemptive Priority Scheduling algorithm with
support for process arrival time, allowing the CPU to schedule the highest-priority process
that has already arrived. Each process is defined by its burst time, priority, and arrival time,
and the scheduler selects the process with the lowest priority number (i.e., higher actual
priority) from the set of available processes. The program calculates and prints each process’s
waiting time and turnaround time, as well as the average waiting and turnaround times. Core
programming concepts include arrays for managing multiple processes, looping and
conditional logic for selection and timing, and manual process selection using priority
comparison. It uses standard libraries like <stdio.h> for input/output, <unistd.h> and
<limits.h> to display the current working directory using getcwd(). The logic ensures that
once a process is executed, it is marked as completed by assigning it unreachable values. The
program outputs results in a tabular format and is suitable for understanding how non-
preemptive priority scheduling works with dynamic arrival of processes.
Code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
void main()
{
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL) {
printf("Running from: %s\n\n", path);
} else {
perror("getcwd() error");
}
int pn = 0; //Processes Number
int CPU = 0; //CPU Current time
int allTime = 0; // Time neded to finish all processes
printf("Enter Processes Count: ");
scanf("%d",&pn);
int AT[pn];
int ATt[pn];
int NoP = pn;
int PT[pn]; //Processes Time
int PP[pn]; //Processes piriorty
int PPt[pn];
int waittingTime[pn];
int turnaroundTime[pn];
int i=0;
//Scanning Time and Piriorty
for(i=0 ;i<pn ;i++){
printf("\nBurst time for P%d: ",i+1);
scanf("%d",&PT[i]);
printf("Piriorty for P%d: ",i+1);
scanf("%d",&PP[i]);
PPt[i] = PP[i];
printf("Arrival Time for P%d: ",i+1);
scanf("%d",&AT[i]);
ATt[i] = AT[i];
}
int j = -1;
while(NoP > 0 && CPU <= 1000){
for(i = 0; i < pn; i++){
if((ATt[i] <= CPU) && (ATt[i] != (LAT+10))){
if(PPt[i] != (MAX_P+1)){
P2 = PPt[i];
j= 1;
if(j == -1){
CPU = CPU+1;
continue;
}else{
}
}
printf("\nPN\tPT\tPP\tAT\tWT\tTT\n\n");
for(i = 0; i < pn; i++){
printf("P%d\t%d\t%d\t%d\t%d\t%d\n",i+1,PT[i],PP[i],AT[i],waittingTime[i],turnaroundTim
e[i]);
}
int AvgWT = 0;
int AVGTaT = 0;
for(i = 0; i < pn; i++){
AvgWT = waittingTime[i] + AvgWT;
AVGTaT = turnaroundTime[i] + AVGTaT;
}
Output:
5. f) WAP to simulate Preemptive Priority Scheduling Algorithm
Theory: The program uses a min-heap (priority queue) implemented with arrays and heap
operations (insert, extractminimum, and order) to efficiently select the highest priority
process at each time unit. Processes are initially sorted by arrival time using qsort, and the
CPU time is simulated step-by-step, allowing preemption after each unit. The program
leverages standard C syntax, including structs, pointers, dynamic arrays, and formatted I/O,
and runs in a Unix-like environment using getcwd to display the current directory.
Code:
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
struct Process {
int processID;
int burstTime;
int tempburstTime;
int arrivalTime;
int priority;
int completionTime;
int turnaroundTime;
int waitingTime;
int intime;
};
void insert(struct Process Heap[], struct Process value, int* heapsize, int* currentTime) {
int start = *heapsize;
Heap[*heapsize] = value;
if (Heap[*heapsize].intime == -1)
Heap[*heapsize].intime = *currentTime;
++(*heapsize);
while (start != 0 && Heap[(start - 1) / 2].priority > Heap[start].priority) {
swap(&Heap[(start - 1) / 2], &Heap[start]);
start = (start - 1) / 2;
}
}
void scheduling(struct Process Heap[], struct Process array[], int n, int* heapsize, int*
currentTime, int ganttProcess[], int ganttStart[], int ganttEnd[], int* gidx) {
if (*heapsize == 0)
return;
struct Process min = extractminimum(Heap, heapsize);
ganttProcess[*gidx] = min.processID;
ganttStart[*gidx] = *currentTime;
--min.burstTime;
(*currentTime)++;
ganttEnd[*gidx] = *currentTime;
(*gidx)++;
if (min.burstTime > 0) {
insert(Heap, min, heapsize, currentTime);
} else {
for (int i = 0; i < n; i++) {
if (array[i].processID == min.processID) {
array[i].completionTime = *currentTime;
break;
}
}
}
}
do {
if (insertedprocess != n) {
for (int i = 0; i < n; i++) {
if (array[i].arrivalTime == currentTime) {
++insertedprocess;
insert(Heap, array[i], &heapsize, ¤tTime);
}
}
}
scheduling(Heap, array, n, &heapsize, ¤tTime, ganttProcess, ganttStart, ganttEnd,
&gidx);
if (heapsize == 0 && insertedprocess == n)
break;
} while (1);
printf("\nGantt Chart:\n");
if (gidx > 0) {
int start = ganttStart[0];
int end = ganttEnd[0];
int pid = ganttProcess[0];
printf("|");
for (int i = 1; i < gidx; i++) {
if (ganttProcess[i] == pid && ganttStart[i] == end) {
end = ganttEnd[i];
} else {
printf(" P%d |", pid);
pid = ganttProcess[i];
start = ganttStart[i];
end = ganttEnd[i];
}
}
printf(" P%d |\n", pid);
start = ganttStart[0];
end = ganttEnd[0];
pid = ganttProcess[0];
printf("%d", start);
for (int i = 1; i < gidx; i++) {
if (ganttProcess[i] == pid && ganttStart[i] == end) {
end = ganttEnd[i];
} else {
printf("%6d", end);
pid = ganttProcess[i];
start = ganttStart[i];
end = ganttEnd[i];
}
}
printf("%6d\n", end);
}
}
int main() {
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL) {
printf("Running from: %s\n\n", path);
} else {
perror("getcwd() error");
}
int n;
printf("Enter number of processes: ");
scanf("%d", &n);
struct Process a[n];
priority(a, n);
return 0;
}
Output:
Theory: It uses arrays and matrices to represent resource allocation (alloc), maximum
demand (max), and available resources (avail), and calculates the remaining needs with the
calculateNeed function. The core function isSafe simulates resource allocation by checking if
processes can complete safely in some order without causing deadlock, using loops and
boolean flags to track finished processes and resource availability (work). The program takes
user input for the number of processes and resources, allocation and max matrices, and
available resources, applying standard C control structures (for, if), arrays, and input/output
functions (scanf, printf) to interactively test system safety. It also uses getcwd to display the
current working directory before execution.
Code:
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <limits.h>
#define MAX_P 10
#define MAX_R 10
bool isSafe(int processes[], int avail[], int max[][MAX_R], int alloc[][MAX_R], int n, int m)
{
int need[MAX_P][MAX_R];
calculateNeed(need, max, alloc, n, m);
int count = 0;
while (count < n) {
bool found = false;
for (int p = 0; p < n; p++) {
if (!finish[p]) {
int j;
for (j = 0; j < m; j++) {
if (need[p][j] > work[j])
break;
}
if (j == m) {
for (int k = 0; k < m; k++)
work[k] += alloc[p][k];
safeSeq[count++] = p;
finish[p] = true;
found = true;
}
}
}
if (!found) {
printf("\nThe system is NOT in a safe state.\n");
return false;
}
}
int main() {
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL) {
printf("Running from: %s\n\n", path);
} else {
perror("getcwd() error");
}
int n, m;
int processes[MAX_P];
int max[MAX_P][MAX_R], alloc[MAX_P][MAX_R], avail[MAX_R];
return 0; }
Output:
6. b) WAP for deadlock detection in the system having multiple type of resources. (The
program should list the deadlocked process in case of deadlock detection results
true)
Theory: This C program implements the Banker's algorithm for deadlock detection. It checks
if processes can safely acquire resources without causing a deadlock by comparing
their maximum need against available resources. The algorithm calculates a need matrix,
simulates resource allocation, and identifies deadlocked processes if any remain unfinished.
The program uses multi-dimensional arrays for resource tracking, loops for matrix
operations, and conditional checks to determine system safety. It also displays the current
directory using getcwd() and takes user input for resource allocation data. The output
confirms whether the system is in a safe state or has deadlocks.
Code:
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <limits.h>
#define MAX_P 10
#define MAX_R 10
void calculateNeed(int need[MAX_P][MAX_R], int max[MAX_P][MAX_R], int
alloc[MAX_P][MAX_R], int n, int m) {
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
need[i][j] = max[i][j] - alloc[i][j];
}
bool detectDeadlock(int processes[], int alloc[][MAX_R], int max[][MAX_R], int avail[], int
n, int m) {
int need[MAX_P][MAX_R];
calculateNeed(need, max, alloc, n, m);
bool progress;
do {
progress = false;
for (int i = 0; i < n; i++) {
if (!finish[i]) {
int j;
for (j = 0; j < m; j++) {
if (need[i][j] > work[j])
break;
}
if (j == m) {
for (int k = 0; k < m; k++)
work[k] += alloc[i][k];
finish[i] = true;
progress = true;
}
}
}
} while (progress);
if (!deadlock_found) {
printf("None");
}
printf("\n");
return deadlock_found;
}
int main() {
char path[PATH_MAX];
if (getcwd(path, sizeof(path)) != NULL)
{
printf("Running from: %s\n\n", path);
}
else
{
perror("getcwd() error");
}
int n, m;
int processes[MAX_P];
int alloc[MAX_P][MAX_R], max[MAX_P][MAX_R], avail[MAX_R];
Output:
Padmakanya Multiple Campus
Bagbazar, Kathmandu
(Tribhuvan University)
LAB REPORT ON