0% found this document useful (0 votes)
11 views

Operating System Project

The document discusses a process scheduling and management system that categorizes processes into three queues based on priority levels. It implements three scheduling algorithms - FCFS, priority sorting, and round robin. It also addresses issues like starvation and deadlock detection and resolution using techniques like aging and preemption.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Operating System Project

The document discusses a process scheduling and management system that categorizes processes into three queues based on priority levels. It implements three scheduling algorithms - FCFS, priority sorting, and round robin. It also addresses issues like starvation and deadlock detection and resolution using techniques like aging and preemption.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Process Scheduling and management

Submitted By: (CS-44)


221030101
221030111
221031028

Submitted To
Dr. Ruchi Verma
Assistant Professor (SG)
Overview
This project implements a process scheduling and management system that categorizes processes
into three queues based on their priority levels. The system uses three different scheduling
algorithms: First Come First Serve (FCFS), Priority Sorting, and Round Robin. Additionally, the
system addresses issues such as starvation and deadlock detection and resolution.

FCFS (First-Come, First-Served)


First-Come, First-Served (FCFS) is one of the simplest scheduling algorithms in operating
systems. In this approach, processes are attended to in the order they arrive in the ready queue. The
process that arrives first is executed first. This method is easy to understand and implement, but it
can lead to the convoy effect , where short processes have to wait for long ones to complete.

Advantages:

• Simple to implement and understand.


• No starvation, as every process gets a fair chance.

Disadvantages:

• Can lead to long waiting times, especially for short processes following long ones.
• Inefficient in terms of average waiting time.

Priority Sorting
Priority Scheduling is a method where each process is assigned a priority, and the process with
the highest priority is executed first. Priorities can be based on various criteria such as resource
requirements, process importance, or urgency.

Advantages:

• Important processes are executed first, which can improve performance in certain scenarios.
• Flexible, as priorities can be adjusted dynamically.

Disadvantages:

• Can lead to starvation of low-priority processes if high-priority processes continue to


arrive.
• Requires a mechanism to assign and adjust priorities, which can be complex.

Round Robin
Round Robin (RR) is a preemptive scheduling algorithm where each process is assigned a fixed
time slot (time quantum) in a cyclic order. When a process's time quantum expires, it is placed at
the end of the ready queue.

Advantages:
• Fair allocation of CPU time to all processes.
• Reduces waiting time for processes as every process gets a turn.

Disadvantages:

• Performance depends heavily on the size of the time quantum. If too small, too much time
is spent on context switching; if too large, it behaves like FCFS.
• Can lead to higher average turnaround times compared to priority-based scheduling.

Starvation
Starvation occurs when a process is perpetually denied necessary resources to proceed with its
execution, often due to the scheduling policy. This typically happens in priority scheduling
algorithms where lower-priority processes may never get executed if higher-priority processes keep
arriving.

Causes:

• Continuous arrival of high-priority processes.


• Inadequate resource allocation mechanisms.

Prevention:

• Implementing aging, where the priority of a process increases the longer it waits.
• Using fair scheduling algorithms like Round Robin.

Deadlock
Deadlock is a situation in operating systems where a set of processes are blocked because each
process is holding a resource and waiting for another resource held by another process. This creates
a cycle of dependencies with no process able to proceed.

Necessary Conditions:

• Mutual Exclusion: At least one resource must be held in a non-sharable mode.


• Hold and Wait: Processes holding resources can request new ones.
• No Preemption: Resources cannot be forcibly taken from processes.
• Circular Wait: A closed chain of processes exists, where each process holds at least one
resource needed by the next process in the chain.

Prevention Techniques:

• Resource allocation algorithms that avoid circular wait.


• Preemption policies to forcibly take resources from processes.
• Ordering resources hierarchically to prevent cycles.
Mutex in Process Scheduling
In our project, mutex (short for "mutual exclusion") is a synchronization mechanism used to
control access to shared resources among multiple threads. This ensures that critical sections of
code are not executed concurrently by more than one thread, which could lead to inconsistent or
incorrect behavior.

Purpose of Mutex in the Project

1. Process Execution Control :

• The process_function simulates the execution of processes. Each process


decreases its remaining_time while it runs. Since multiple threads could
modify the remaining_time of their respective processes concurrently, we use a
mutex to prevent race conditions.
• Mutex locks ensure that only one thread at a time can modify the shared resource
( remaining_time ), maintaining data consistency and preventing unexpected
behavior.
2. Memory Allocation :

• Although not explicitly protected by mutex in the provided code, any real-world
memory management (e.g., allocateMemory and freeMemory ) that involves
concurrent access should be protected by mutexes to prevent memory corruption.

Threading in Process Scheduling


Threading is a programming technique used to achieve concurrency within a single process. In our
project, threading is employed to simulate the concurrent execution of multiple processes, each
running independently.

Purpose of Threading in the Project

1. Concurrent Process Execution :

• Threading allows multiple processes to execute concurrently, mimicking the


behavior of a multitasking operating system.
• Each thread represents a process, and they run simultaneously, interacting with
shared resources such as CPU time and memory.
2. Efficient Resource Utilization :

• By running processes concurrently, threading maximizes CPU utilization, reducing


idle time and improving overall system efficiency.
File Structure
The project consists of the following files:

1)main.c

2)process.h

3)fcfs.c

4)priority_sorting.c

5)round_robin.c

6)starvation.c

7)memory_management.c

Header File: process.h

// process.h
#ifndef PROCESS_H
#define PROCESS_H

#include <pthread.h>

// Constants
#define MEMORY_SIZE 1000

// Process structure
struct process {
int priority;
int burst_time;
int pid;
int waiting_time;
int turnaround_time;
int remaining_time;
int arrival_time;
};

// Shared variables
extern pthread_mutex_t lock;
extern int memory[MEMORY_SIZE];
extern int allocated_memory;
extern int time_quantum;
extern int q1_n, q2_n, q3_n, n;
extern struct process *q1, *q2, *q3;

// Function prototypes
void getInput();
void calcWaitingTime(struct process *q, int size);
void calcTurnAroundTime(struct process *q, int size);
void printQueue(struct process *q, int size);
void printQueueI(struct process p);
void* process_function(void* arg);
int allocateMemory(int size);
void freeMemory(int start, int size);
void startThreads();
int isStarvation(struct process* q, int size, int threshold);
void resolveStarvation(struct process* q, int size, int threshold);
void detectAndResolveDeadlock();
void FCFS();
void PrioSorting();
void RoundRobin();
#endif // PROCESS_H

Main File: main.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "process.h"

pthread_mutex_t lock;
int memory[MEMORY_SIZE];
int allocated_memory = 0;

// Time Quantum
int time_quantum = 4;

int q1_n = 0, q2_n = 0, q3_n = 0, n = 0; // N = Total Process


struct process *q1, *q2, *q3;

void getInput() {
printf("\n Total Number of Process:\t");
scanf("%d", &n);
// Allocating Memory
q1 = (struct process *)malloc(n * sizeof(struct process));
q2 = (struct process *)malloc(n * sizeof(struct process));
q3 = (struct process *)malloc(n * sizeof(struct process));
for (int i = 0; i < n; i++) {
struct process p;
printf("\n\t\tProcess %d\n=============================================\n\n",
i + 1);
p.arrival_time = (rand()) % (n + 1);
printf("PId:\t");
scanf("%d", &p.pid);
printf("Priority (1-9):\t");
scanf("%d", &p.priority);
printf("\nBurst Time: ");
scanf("%d", &p.burst_time);
p.remaining_time = p.burst_time;
if (p.priority > 0 && p.priority <= 3) {
q1[q1_n++] = p;
} else if (p.priority > 3 && p.priority <= 6) {
q2[q2_n++] = p;
} else {
q3[q3_n++] = p;
}
}
}

int main() {
getInput();
int i = 1;
int starvation_threshold = 10; // Example threshold for detecting starvation
while (n > 0) {
switch (i) {
case 3:
RoundRobin();
break;
case 2:
PrioSorting();
break;
case 1:
FCFS();
break;
}
// Check for starvation in all queues
if (isStarvation(q1, q1_n, starvation_threshold)) {
printf("\nStarvation detected in FCFS queue. Resolving starvation...\n");
resolveStarvation(q1, q1_n, starvation_threshold);
}
if (isStarvation(q2, q2_n, starvation_threshold)) {
printf("\nStarvation detected in Priority Sorting queue. Resolving starvation...\n");
resolveStarvation(q2, q2_n, starvation_threshold);
}
if (isStarvation(q3, q3_n, starvation_threshold)) {
printf("\nStarvation detected in Round Robin queue. Resolving starvation...\n");
resolveStarvation(q3, q3_n, starvation_threshold);
}
detectAndResolveDeadlock();
startThreads(); // Start thread execution
i = (i % 3) + 1;
sleep(2);
}
printf("\n\n");
return 0;
}

// fcfs.c

#include <stdio.h>
#include "process.h"
void FCFSAlgorithm(struct process *q, int size) {
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (q[j].arrival_time < q[i].arrival_time) {
struct process t = q[i];
q[i] = q[j];
q[j] = t;
}
}
}
}

void FCFS() {
printf("\n\
n=====================================================================
======\n");
printf("\t\tFirst Come First Serve\t");
printf("\
n=====================================================================
======\n\n");
FCFSAlgorithm(q1, q1_n);
printQueue(q1, q1_n);
}

Priority Sorting Implementation: priority_sorting.c


// priority_sorting.c
#include <stdio.h>
#include "process.h"

void PrioSortingAlgorithm(struct process *q, int size) {


for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (q[j].priority < q[i].priority) {
struct process t = q[i];
q[i] = q[j];
q[j] = t;
}
}
}
}
void PrioSorting() {
printf("\n\
n===========================================================================\
n");
printf("\t\tPriority Sorting\t");
printf("\
n===========================================================================\n\
n");
PrioSortingAlgorithm(q2, q2_n);
printQueue(q2, q2_n);
}

Round Robin Implementation: round_robin.c

// round_robin.c
#include <stdio.h>
#include "process.h"

void RoundRobinAlgo(struct process *q, int size) {


int time = 0, i = 0, remain = size, flag = 0, wait_time = 0, tat_time = 0;
for (time = 0, i = 0; remain != 0; ) {
struct process *p = &q[i];
if (p->remaining_time <= time_quantum && p->remaining_time > 0) {
time += p->remaining_time;
p->remaining_time = 0;
flag = 1;
} else if (p->remaining_time > time_quantum) {
p->remaining_time -= time_quantum;
time += time_quantum;
}
if (p->remaining_time == 0 && flag == 1) {
remain--;
printf("\n%d\t\t%d\t\t\t%d\t\t\t%d\t\t\t%d", p->pid, p->priority,
p->burst_time, p->waiting_time, p->turnaround_time);
wait_time += time - p->arrival_time - p->burst_time;
tat_time += time - p->arrival_time;
flag = 0;
}

if (i == size - 1) {
i = 0;
} else if (q[i + 1].arrival_time < time) {
i++;
} else {
i = 0;
}
}
printf("\nAverage Waiting Time= %f\n", wait_time * 1.0 / size);
printf("Avg Turnaround Time = %f\n", tat_time * 1.0 / size);
}

void RoundRobin() {
printf("\n\
n===========================================================================\
n");
printf("\t\tRound Robin\t");
printf("\
n===========================================================================\n\
n");
printf("\nPId\t\tPriority\t\tBurst Time\t\tWaiting Time\t\tTurnAround
Time");
printf("\
n==============================================================================
==\n");
calcWaitingTime(q3, q3_n);
calcTurnAroundTime(q3, q3_n);

RoundRobinAlgo(q3, q3_n);
}

Starvation Detection and Resolution: starvation.c

// starvation.c
#include <stdio.h>
#include "process.h"

int isStarvation(struct process* q, int size, int threshold) {


for (int i = 0; i < size; i++) {
if (q[i].waiting_time > threshold) {
return 1;
}
}
return 0;
}

void resolveStarvation(struct process* q, int size, int threshold) {


for (int i = 0; i < size; i++) {
if (q[i].waiting_time > threshold) {
// Boost priority or reduce waiting time
q[i].priority = 1; // Boost priority to highest
q[i].waiting_time = 0; // Reset waiting time
}
}
}

Memory Management: memory_management.c

// memory_management.c
#include <stdio.h>
#include "process.h"

int allocateMemory(int size) {


if (allocated_memory + size <= MEMORY_SIZE) {
allocated_memory += size;
return allocated_memory - size;
} else {
return -1; // Memory allocation failed
}
}

void freeMemory(int start, int size) {


allocated_memory -= size;
}

You might also like