os_ansh

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 40

OPERATING SYSTEM LAB

Ansh Kasaudhan

2023-2024

BCS-451

Under the Guidance of
Mr. Deepak Singh Sir
2
INTRODUCTION

This Operating System lab report explores


fundamental concepts and practical
applications of operating systems. It covers
essential topics such as process management,
memory management, file systems, and
system security. The experiments conducted
aim to enhance understanding of how an OS
functions, its role in managing hardware and
software resources, and its importance in
ensuring efficient system performance.
Through hands-on activities, students gain
insights into the intricacies of process
scheduling, inter-process communication,
memory allocation strategies, and file system
architecture. This report documents the
methodologies, observations, and
conclusions drawn from the lab exercises,
providing a comprehensive understanding of
operating system principles.

PAGE 2
3

Index
S. Name of Date of Date of Page Teacher’s
No Program Conduction checking No. Sign
1. (i) To understand OS functionalities like
system configuration, device manager,
and group policy.
(ii) Understand the minimum
requirements of different Operating
System like Window XP, Window 8.1
and higher, Linux, Unix, Mac OS.
2. Basics of UNIX/ DOS Commands.
3. Implementation of CPU Scheduling.
(i) FCFS, (ii) SJF
4. Implementation of CPU Scheduling.
( i ) Shortest Remaining Time First
(ii) Priority based
5. Implementation of CPU Scheduling:
(i) Round Robin (ii) Longest Job First.
6. Implementation of Process and thread
(Life cycle of process): (i) Process
creation and Termination; (ii) Thread
creation and Termination
7. Producer-Consumer Problem using
Semaphores and Reader Writer Problem
8. Simulate algorithm for deadlock
prevention and detection
9. Simulate the algorithm for deadlock
avoidance and study about deadlock
recovery.
10. Simulate memory allocation methods:
(i) Best Fit, (ii) Worst Fit and (iii)
Next Fit
11. Simulate page replacement algorithms:
FIFO, LRU and Optimal.
12. Implementation of Disk Scheduling
using FCFS, SCAN and C-SCAN
algorithm
13. Implementation of Disk Scheduling
using LOOK, C-LOOK and SSTF
algorithm
4

Program 1
Aim: - (i) To understand OS functionalities like system configuration, device manager, and
group policy.

Theory: -
MSconfig

MSConfig (officially called System Configuration in Windows Vista, Windows 7, Windows


8, Windows 10, or Windows 11 and Microsoft System Configuration Utility in previous
operating systems) is a system utility to troubleshoot the Microsoft Windows startup process.
It can disable or re-enable software, device drivers and Windows services that run at startup,
or change boot parameters.

Steps to open System Configuration


Option 1: Open Local Group Policy Editor in Run

• Open Search in the Toolbar and type Run, or select Run from your Start Menu.
• Type ‘msconfig’ in the Run command and click OK.

Option 2: Open Local Group Policy Editor in Search

• Open Search on the Toolbar


• Type ‘msconfig’ and click ‘System Configuration.’

Option 3: Open Local Group Policy Editor in Command Prompt

• From the Command Prompt, type ‘msconfig’ and hit ‘Enter.’

Option 4: Open Local Group Policy Editor in PowerShell

• In PowerShell, type ‘msconfig’ and then ‘Enter.’

System Configuration Features


Here are the main features and tabs available in msconfig:

General Tab

1. Normal Startup:
• Loads all device drivers and services.
2. Diagnostic Startup:
• Loads basic devices and services only, similar to Safe Mode.
3. Selective Startup:
• Allows the user to select which programs and services to load.
Boot Tab 5

1. Boot Options:
• Safe Boot: Boots Windows in Safe Mode with different sub-options:
o Minimal: Basic Safe Mode.
o Alternate Shell: Safe Mode with Command Prompt.
o Active Directory Repair: Used to repair the Active Directory server.
o Network: Safe Mode with networking.
• No GUI Boot: Boots without the Windows GUI (graphical user interface).
• Boot Log: Creates a file of the boot process.
• Base Video: Boots using basic video drivers.
• OS Boot Information: Displays drivers being loaded during boot.
• Timeout: Specifies the time to display the list of operating systems.
2. Advanced Options:
• Number of processors: Limits the number of processors to use.
• Maximum memory: Limits the amount of memory used.
• Debugging mode: Enables debugging.

Tools Tab

• Provides quick access to various system tools and utilities, such as:
• System Information
• Event Viewer
• Performance Monitor
• Command Prompt
• Registry Editor
• Task Manager

These features of msconfig make it a powerful utility for managing the boot process and troubleshooting
startup issues in Windows.

Gpedit.msc
The Group Policy Editor is a Windows administration tool that allows users to configure many important
settings on their computers or networks. Administrators can configure password requirements, startup
programs, and define what applications or settings users can change.
6
Steps to open Group policy editor
Option 1: Open Local Group Policy Editor in Run

• Open Search in the Toolbar and type Run, or select Run from your Start Menu.
• Type ‘gpedit.msc’ in the Run command and click OK.

Option 2: Open Local Group Policy Editor in Search

• Open Search on the Toolbar


• Type ‘gpedit’ and click ‘Edit Group Policy.’

Option 3: Open Local Group Policy Editor in Command Prompt

• From the Command Prompt, type ‘gpedit.msc’ and hit ‘Enter.’

Option 4: Open Local Group Policy Editor in PowerShell

• In PowerShell, type ‘gpedit’ and then ‘Enter.’

Option 5: Open Local Group Policy Editor in Start Menu Control Panel

• Open the Control Panel on the Start Menu.


• Click the Windows icon on the Toolbar, and then click the widget icon for Settings.
• Start typing ‘group policy’ or ‘gpedit’ and click the ‘Edit Group Policy’ option.

Components of Group policy editor


The top-level nodes on the left are “Computer Configuration” and “User Configuration.” If you open the tree
for Computer Configuration, you can explore the options you have to manage different system behavior
aspects. For example, under Computer Configuration -> Administrative Templates -> Control Panel ->
Personalization, you will see things like “Do not display the lock screen” on the right side. You can edit the
setting by double-clicking.

There are hundreds of different settings like this in Group Policy Editor.

Local Group Policy Editor Components

• Computer Configuration: These policies apply to the local computer, and do not change per user.
• User Configuration: These policies apply to users on the local machine, and will apply to any new
users in the future, on this local computer.
• Those two main categories are further broken down into sub-categories:
• Software Settings: Software settings contain software specific group policies: this setting is empty by
default.
7

Regedit
The Windows Registry Editor (regedit) is a graphical tool in the Microsoft Windows operating system (OS)
that enables authorized users to view the Windows registry and make changes.
The Windows registry, also known as the registry, is a hierarchical database that stores the configuration
settings required for a computer to operate efficiently. This information includes basic boot-up functions, user
profile information, startup options, installed applications and drivers, system hardware information and
specific design settings.

Steps to open Registry Editor


Option 1: Open Local Group Policy Editor in Run

• Open Search in the Toolbar and type Run, or select Run from your Start Menu.
• Type ‘regedit’ in the Run command and click OK.

Option 2: Open Local Group Policy Editor in Search

• Open Search on the Toolbar


• Type ‘regedit’ and click ‘Registry Editor.’

Option 3: Open Local Group Policy Editor in Command Prompt

• From the Command Prompt, type ‘regedit’ and hit ‘Enter.’

Option 4: Open Local Group Policy Editor in PowerShell

• In PowerShell, type ‘regedit’ and then ‘Enter.’

Registry Editor Features


1. Viewing and Navigating the Registry:

• Hierarchical Structure: The registry is organized in a tree-like structure with keys and subkeys,
similar to folders and files in a filesystem. The main root keys include:
o HKEY_CLASSES_ROOT (HKCR): Contains information about registered applications,
file associations, and COM objects.
o HKEY_CURRENT_USER (HKCU): Stores settings specific to the current user.
o HKEY_LOCAL_MACHINE (HKLM): Contains settings that apply to the local
machine, regardless of the user.
o HKEY_USERS (HKU): Contains user-specific settings for all users on the system.
o
o HKEY_CURRENT_CONFIG (HKCC): Contains hardware profile information used
8 at
system startup.

2. Editing Keys and Values:

• Keys: Like folders in the file system, they can contain subkeys and values.
• Values: Come in several types, including:
o String (REG_SZ): A fixed-length text string.
o Binary (REG_BINARY): Raw binary data.
o DWORD (REG_DWORD): A 32-bit number.
o QWORD (REG_QWORD): A 64-bit number.
o Multi-String (REG_MULTI_SZ): An array of strings.
o Expandable String (REG_EXPAND_SZ): A string that contains environment variables.
• Users can add, modify, delete, and rename keys and values.

3. Searching the Registry:

• Find: Allows users to search for specific keys, values, or data within the registry.
• Find Next: Continues the search from the current location.

4. Exporting and Importing:

• Export: Allows users to save a part or the entirety of the registry to a file, which can be used for
backup purposes or for transferring settings to another machine.
• Import: Enables users to load a previously exported registry file, merging its contents with the
current registry.

5. Permissions:

• Users can set permissions on keys to control access, allowing or denying specific users or groups
the ability to read or modify certain keys.

6. Favorites:

• Users can add frequently accessed keys to a favorites list for quick access.

7. View Options:

• Split View: Users can split the view to see different parts of the registry simultaneously.
• Status Bar: Shows the path of the selected key and the number of subkeys and values it contains.
9

Aim: - (ii) Understand the minimum requirements of different Operating System like
Window XP, Window 8.1 and higher, Linux, Unix, Mac OS.

Theory: -This section aims to outline and compare the minimum hardware and software
requirements for various popular operating systems, including Windows XP, Windows 8.1
and higher, Linux, Unix, and Mac OS. Understanding these requirements is crucial for
system compatibility and optimal performance.

Hardware Requirements: -Hardware requirements refer to the minimum and recommended


physical components needed for an operating system (OS) to function correctly. These components
include:

Processor (CPU): The central processing unit's speed and capabilities, measured in gigahertz
(GHz), affect the system's ability to execute tasks. Different OS versions have varying minimum CPU
requirements to ensure smooth operation.
Memory (RAM): Random-access memory is critical for multitasking and running applications.
Higher RAM allows for better performance and handling of more demanding software.
Storage (Hard Drive/SSD): The amount of available storage space is necessary for the OS
installation and for storing applications and files. Solid-state drives (SSDs) offer faster data access
speeds compared to traditional hard drives (HDDs).
Graphics Card: A dedicated or integrated graphics processing unit (GPU) is essential for
rendering images, videos, and graphical interfaces. Some OS require specific graphics capabilities to
support advanced features.
Other Peripherals: Input and output devices like keyboards, mice, monitors, and printers may
have specific requirements based on the OS.

Software Requirements: -Software requirements include the necessary software components


and dependencies needed for an OS to operate efficiently. These include:

OS Kernel: The core component of the operating system that manages hardware resources and
facilitates interactions between hardware and software.
Drivers: Software that allows the OS to communicate with hardware devices such as printers,
graphics cards, and network adapters.
Utilities: Essential tools and programs that come with the OS to perform system maintenance
and management tasks.
Libraries: Pre-compiled code modules that applications can use to perform common functions
without having to write code from scratch. These are often required for running certain applications.
Compatibility: Specific software versions or features that must be present for the OS to function
correctly with other installed applications.
Security Software: Built-in or additional antivirus and firewall programs to protect the system
from malware and unauthorized access.

Hardware and Software Requirements for Different Operating Systems


1. Windows XP 10
(a) Hardware:
Processor: - Minimum 233 MHz, recommended 300 MHz
RAM: - Minimum 64 MB, recommended 128 MB
Hard Drive: -1.5 GB available space
Graphics: -Super VGA (800 x 600) or higher resolution
(b)Software:
DirectX: - Version 8.0 or higher
Other: - Internet Explorer 6, additional drivers for peripherals
2. Windows 8.1 and Higher
(a) Hardware:
Processor: - 1 GHz with support for PAE, NX, and SSE2
RAM: - 1 GB (32-bit) or 2 GB (64-bit)
Hard Drive: -16 GB (32-bit) or 20 GB (64-bit)
Graphics: - Microsoft DirectX 9 graphics device with WDDM driver
(b)Software:
DirectX: - Version 9 or higher
Other: - Microsoft account for some features, Windows Store access
3. Linux (example for a typical distribution)
(a) Hardware:
Processor: - Minimum 700 MHz, recommended 1 GHz
RAM: - Minimum 512 MB, recommended 1 GB
Hard Drive: -5 GB available space minimum
Graphics: - VGA capable of 1024x768 resolution
(b)Software:
DirectX: - Version 3.2 or higher
Other: - GNU utilities, X Window System for GUI, package manager for
software installation
4. Unix (general-purpose example)
(a) Hardware:
Processor: - Minimum 500 MHz
RAM: - Minimum 256 MB
Hard Drive: -2 GB available space
Graphics: - Standard VGA
(b)Software:
DirectX: - System V or BSD-based
Other: - Shell utilities, optional GUI components like X Window System
5. Mac OS (example for macOS Catalina)
(a) Hardware:
Processor: - Intel Core i5
RAM: - 4 GB
Hard Drive: -12.5 GB available space for installation
Graphics: - Metal-capable graphics card
(b)Software:
DirectX: - macOS Catalina or higher
Other: - Apple ID for iCloud and App Store access, compatible applications from
the Mac App Store
11

Program 2
Aim: - Basics of UNIX/ DOS Commands.

Theory: -
MS Dos Commands

Dir List all files of specific directories or subdirectories.

CD or CHDIR Navigate or move to a specific directory.

RD or RMDIR Remove directory.

TREE Display all directory paths.

PATH Set sequential search path for executable files.

SUBST Substitutes a string alias for the pathname.

FORMAT Formats a disk for DOS files.

COPY Copies one or more files to another location.

XCOPY Copy files and directories and their subdirectories.

Del Delete files.

Ren or rename Rename the name of a file or directory.

ATTRIB Set or show file attributes.

BACKUP Backup files and directories.

PROMPT Customize DOS prompt.

Deltree Deletes all files and subdirectories from a computer.

Help Lists the available commands or more information about a


specific command.

mkdir or md Creates a new subdirectory.

Move Moves files or directories from one directory to another or


from one drive to another.

Type Displays the contents of a file on the screen.


12

MS-DOS is a text-based system of Microsoft Operating System; The users interact with the
computer by typing text-based commands rather than a Graphical User Interface. These
commands allow users to perform various tasks, such as copying, deleting, or moving files,
and managing programs.

MS Dos has used for following purposes: -

File Management: MS Dos commands enable users to navigate through directories and
create, delete, or copy files, enabling efficient file management.
System Configuration: Users can configure system settings, manage drives, and analyze
hardware issues using MS Dos commands, providing a robust toolkit for system
customization.
Program Execution: MS Dos for commands facilitate the execution of programs and scripts,
offering a streamlined approach to launching applications without the need for graphical
interfaces.

Steps to Open Command Prompt

1. Select the Start Menu (the Windows icon) in the taskbar, or press the Windows key.
2. Type cmd.
3. Select Command Prompt from the list.

If you're using the latest version of Windows 11, Command Prompt will open
within Terminal.
13

Program 3
Aim - Implementation of CPU Scheduling. (i) FCFS, (ii) SJF

Theory: -
FCFS Algorithm

DESCRIPTION: -The process that arrives first is executed first.

Algorithm: -

1. Initialize Variables: Declare arrays for process IDs, burst times, arrival times, completion times, turn-
around times, and waiting times. Initialize variables for total waiting time and total turn-around time.
2. Input Number of Processes: Ask the user for the number of processes (n) and store the input.
3. Input Burst Time and Arrival Time: For each process, prompt the user to input the burst time and
arrival time.
4. Calculate CT, TAT, WT:
• Set current_time to 0.
• For each process:
o If current_time is less than the arrival time, set it to the arrival time.
o Calculate completion time (ct[i]) as current_time + bt[i].
o Update current_time to ct[i].
o Calculate turn-around time (tat[i]) as ct[i] - at[i].
o Calculate waiting time (wt[i]) as tat[i] - bt[i].

5. Display Process Details: Print the process ID, burst time, arrival time, completion time, turn-around
time, and waiting time for each process.
6. Calculate and Display Averages: Calculate average waiting time (avg_wt) and average turn-around
time (avg_tat). Print these averages.

Code: -
#include <stdio.h>
// Function to find the completion time, turn around time and waiting time for all
processes
void findCT_TAT_WT(int processes[], int n, int bt[], int at[], int ct[], int tat[], int wt[]) {
int current_time = 0;

for (int i = 0; i < n; i++) {


if (current_time < at[i]) {
current_time = at[i];
}
ct[i] = current_time + bt[i];
current_time = ct[i];
tat[i] = ct[i] - at[i];
wt[i] = tat[i] - bt[i];
}
}
14
// Function to calculate average time
void findavgTime(int processes[], int n, int bt[], int at[]) {
int ct[n], tat[n], wt[n];
int total_wt = 0, total_tat = 0;

// Function to find completion time, turn around time and waiting time for all processes
findCT_TAT_WT(processes, n, bt, at, ct, tat, wt);

// Display processes along with all details


printf("Processes Burst time Arrival time Completion time Turn around time
Waiting time\n");
// Calculate total waiting time and total turn around time
for (int i = 0; i < n; i++) {
total_wt += wt[i];
total_tat += tat[i];
printf(" %d ", (i + 1));
printf(" %d ", bt[i]);
printf(" %d ", at[i]);
printf(" %d ", ct[i]);
printf(" %d ", tat[i]);
printf(" %d\n", wt[i]);
}
float avg_wt = (float) total_wt / n;
float avg_tat = (float) total_tat / n;
printf("Average waiting time = %f\n", avg_wt);
printf("Average turn around time = %f\n", avg_tat);
}
int main() {
int n;
// Input number of processes
printf("Enter number of processes: ");
scanf("%d", &n);
int processes[n];
int burst_time[n];
int arrival_time[n];
// Input burst time and arrival time for each process
for (int i = 0; i < n; i++) {
processes[i] = i + 1; // Process IDs
printf("Enter burst time for process %d: ", i + 1);
scanf("%d", &burst_time[i]);
printf("Enter arrival time for process %d: ", i + 1);
scanf("%d", &arrival_time[i]);
}

findavgTime(processes, n, burst_time, arrival_time);


return 0;
}
15
Output: -

SJF Algorithm

DESCRIPTION: -The job which has shortest burst time is executed first.

Algorithm: -

1) Initialize Variables: Declare arrays for process IDs, burst times, arrival times, completion times, turn-
around times, and waiting times. Initialize variables for total waiting time and total turn-around time.
2) Input Number of Processes: Ask the user for the number of processes (n) and store the input.
3) Input Burst Time and Arrival Time: For each process, prompt the user to input the burst time.
4) Sort Processes by Burst Time: Sort the processes based on their burst times in ascending order.
5) Calculate CT, TAT, WT:

• Set current_time to 0.
• For each process in sorted order:
o Calculate completion time (ct[i]) as current_time + bt[i].
o Update current_time to ct[i].
o Calculate turn-around time (tat[i]) as ct[i] - at[i].
o Calculate waiting time (wt[i]) as tat[i] - bt[i].

6) Display Process Details: Print the process ID, burst time, arrival time, completion time, turn-around time,
and waiting time for each process.
7) Calculate and Display Averages: Calculate average waiting time (avg_wt) and average turn-around time
(avg_tat). Print these averages.
16
Code: -
#include <stdio.h>

// Function to sort processes based on burst time (SJF)


void sortProcesses(int bt[], int at[], int n, int processes[]) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (bt[j] > bt[j + 1]) {
// Swap burst time
int temp = bt[j];
bt[j] = bt[j + 1];
bt[j + 1] = temp;

// Swap arrival time


temp = at[j];
at[j] = at[j + 1];
at[j + 1] = temp;

// Swap process IDs


temp = processes[j];
processes[j] = processes[j + 1];
processes[j + 1] = temp;
}
}
}
}

// Function to find completion time, turn around time and waiting time for all processes
void findCT_TAT_WT(int processes[], int n, int bt[], int at[], int ct[], int tat[], int wt[]) {
int current_time = 0;

for (int i = 0; i < n; i++) {


if (current_time < at[i]) {
current_time = at[i];
}
ct[i] = current_time + bt[i];
current_time = ct[i];
tat[i] = ct[i] - at[i];
wt[i] = tat[i] - bt[i];
}
}

// Function to calculate average time


void findavgTime(int processes[], int n, int bt[], int at[]) {
int ct[n], tat[n], wt[n];
int total_wt = 0, total_tat = 0;
17
// Sort processes based on burst time (SJF)
sortProcesses(bt, at, n, processes);

// Find completion time, turn around time and waiting time for all processes
findCT_TAT_WT(processes, n, bt, at, ct, tat, wt);

// Display processes along with all details


printf("Processes Burst time Arrival time Completion time Turn around time
Waiting time\n");
for (int i = 0; i < n; i++) {
total_wt += wt[i];
total_tat += tat[i];
printf(" %d ", processes[i]);
printf(" %d ", bt[i]);
printf(" %d ", at[i]);
printf(" %d ", ct[i]);
printf(" %d ", tat[i]);
printf(" %d\n", wt[i]);
}

float avg_wt = (float) total_wt / n;


float avg_tat = (float) total_tat / n;
printf("Average waiting time = %f\n", avg_wt);
printf("Average turn around time = %f\n", avg_tat);
}

// Driver code
int main() {
int n;

// Input number of processes


printf("Enter number of processes: ");
scanf("%d", &n);

int processes[n];
int burst_time[n];
int arrival_time[n];

// Input burst time and arrival time for each process


for (int i = 0; i < n; i++) {
processes[i] = i + 1; // Process IDs
printf("Enter burst time for process %d: ", i + 1);
scanf("%d", &burst_time[i]);
printf("Enter arrival time for process %d: ", i + 1);
scanf("%d", &arrival_time[i]);
}
// Calculate average waiting time and average turn-around time 18
findavgTime(processes, n, burst_time, arrival_time);
return 0;
}

Output: -
19

Program 4
Aim: - Implementation of CPU Scheduling. (i) Shortest Remaining Time First
(ii) Priority based

Theory: -
SRTF Algorithm

DESCRIPTION: -The process that have shortest remaining time is executed first.

Algorithm: -
1. Initialize Variables:
• Declare arrays for process IDs, burst times, arrival times, completion times, turn-around times,
and waiting times.
• Initialize remaining time for each process, current time, and completed process count.
2. Input Number of Processes:
• Prompt user for number of processes (n) and store it.
3. Input Burst Time and Arrival Time for Each Process:
• For each process, get burst time and arrival time from user.
4. Find Shortest Remaining Job:
• Create a function to find the process with shortest remaining time among arrived and
uncompleted processes.
5. Calculate Completion Time, Turn-Around Time, and Waiting Time:
• Loop until all processes are completed:
• Find process with shortest remaining time.
• If process found:
o Reduce its remaining time by 1.
o Update current time.
o If remaining time becomes 0, calculate completion time, turn-around time, and waiting
time.
6. Display Process Details:
• Print process ID, burst time, arrival time, completion time, turn-around time, and waiting time
for each process.
7. Calculate and Display Averages:
• Calculate average waiting time and average turn-around time.
• Print these averages.

Code: -
#include <stdio.h>
#include <limits.h>

// Function to find process with shortest remaining time


int findShortestJob(int bt[], int at[], int rt[], int n, int currentTime) {
int shortest = INT_MAX;
int shortestIndex = -1;
for (int i = 0; i < n; i++) { 20
if (at[i] <= currentTime && rt[i] < shortest && rt[i] > 0) {
shortest = rt[i];
shortestIndex = i;
}
}

return shortestIndex;
}

// Function to find completion time, turn-around time and waiting time for all processes
void findCT_TAT_WT(int processes[], int n, int bt[], int at[], int ct[], int tat[], int wt[]) {
int rt[n];

// Initialize remaining time to burst time


for (int i = 0; i < n; i++) {
rt[i] = bt[i];
}

int currentTime = 0;
int completed = 0;

while (completed != n) {
int shortestJobIndex = findShortestJob(bt, at, rt, n, currentTime);

if (shortestJobIndex == -1) {
currentTime++;
continue;
}

// Reduce remaining time of selected process by 1


rt[shortestJobIndex]--;

// Update current time


currentTime++;

// If a process is completed
if (rt[shortestJobIndex] == 0) {
completed++;

// Calculate completion time


ct[shortestJobIndex] = currentTime;

// Calculate turn-around time


tat[shortestJobIndex] = ct[shortestJobIndex] - at[shortestJobIndex];

// Calculate waiting time


wt[shortestJobIndex] = tat[shortestJobIndex] - bt[shortestJobIndex];
}
}
}

// Function to calculate average time


void findavgTime(int processes[], int n, int bt[], int at[]) {
int ct[n], tat[n], wt[n];
int total_wt = 0, total_tat = 0;
21
// Find completion time, turn around time and waiting time for all processes
findCT_TAT_WT(processes, n, bt, at, ct, tat, wt);

// Display processes along with all details


printf("Processes Burst time Arrival time Completion time Turn around time Waiting time\n");
for (int i = 0; i < n; i++) {
total_wt += wt[i];
total_tat += tat[i];
printf(" %d ", processes[i]);
printf(" %d ", bt[i]);
printf(" %d ", at[i]);
printf(" %d ", ct[i]);
printf(" %d ", tat[i]);
printf(" %d\n", wt[i]);
}

float avg_wt = (float) total_wt / n;


float avg_tat = (float) total_tat / n;
printf("Average waiting time = %f\n", avg_wt);
printf("Average turn around time = %f\n", avg_tat);
}

// Driver code
int main() {
int n;

// Input number of processes


printf("Enter number of processes: ");
scanf("%d", &n);

int processes[n];
int burst_time[n];
int arrival_time[n];

// Input burst time and arrival time for each process


for (int i = 0; i < n; i++) {
processes[i] = i + 1; // Process IDs
printf("Enter burst time for process %d: ", i + 1);
scanf("%d", &burst_time[i]);
printf("Enter arrival time for process %d: ", i + 1);
scanf("%d", &arrival_time[i]);
}

// Calculate average waiting time and average turn-around time


findavgTime(processes, n, burst_time, arrival_time);
return 0;
}
22
Output: -

Priority Algorithm

DESCRIPTION: - The process which ha highest priority (lowest number or vice versa) is
executed first.

Algorithm: -

1. Initialize Variables:
• Declare arrays for process IDs, burst times, arrival times, priorities, completion times, turn-
around times, and waiting times.
2. Input Number of Processes:
• Prompt the user for the number of processes (n) and store the input.
3. Input Process Details:
• For each process:
o Prompt the user to input burst time, arrival time, and priority.
4. Sort Processes by Priority:
• Sort the processes based on their priorities in ascending order.
5. Calculate Completion Time, Turn-Around Time, and Waiting Time:
• Initialize current time to 0.
• Loop through the sorted processes:
o Calculate completion time, turn-around time, and waiting time for each process.
6. Display Process Details:
• Print process ID, burst time, arrival time, priority, completion time, turn-around time, and
waiting time for each process.
7. Calculate and Display Averages:
• Calculate average waiting time and average turn-around time.
• Print these averages.
Code: - 23
#include <stdio.h>
#include <stdbool.h>

// Function to sort processes based on priority


void sortProcessesByPriority(int processes[], int bt[], int at[], int priority[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (priority[j] > priority[j + 1]) {
// Swap process details
int temp = processes[j];
processes[j] = processes[j + 1];
processes[j + 1] = temp;

temp = bt[j];
bt[j] = bt[j + 1];
bt[j + 1] = temp;

temp = at[j];
at[j] = at[j + 1];
at[j + 1] = temp;

temp = priority[j];
priority[j] = priority[j + 1];
priority[j + 1] = temp;
}
}
}
}

// Function to find completion time, turn-around time, and waiting time for all processes
void findCT_TAT_WT(int processes[], int n, int bt[], int at[], int priority[], int ct[], int tat[], int wt[]) {
int currentTime = 0;

for (int i = 0; i < n; i++) {


if (currentTime < at[i]) {
currentTime = at[i];
}
ct[i] = currentTime + bt[i];
currentTime = ct[i];
tat[i] = ct[i] - at[i];
wt[i] = tat[i] - bt[i];
}
}

// Function to calculate average time


void findavgTime(int processes[], int n, int bt[], int at[], int priority[]) {
int ct[n], tat[n], wt[n];
int total_wt = 0, total_tat = 0;
bool isPresent = false;

// Sort processes by priority


sortProcessesByPriority(processes, bt, at, priority, n);
// Find completion time, turn-around time, and waiting time for all processes 24
findCT_TAT_WT(processes, n, bt, at, priority, ct, tat, wt);

// Display processes along with all details


printf("Processes Burst time Arrival time Priority Completion time Turn around time Waiting
time\n");
for (int i = 0; i < n; i++) {
// Check if process is present based on arrival time
if (ct[i] != 0) {
isPresent = true;
total_wt += wt[i];
total_tat += tat[i];
printf(" %d ", processes[i]);
printf(" %d ", bt[i]);
printf(" %d ", at[i]);
printf(" %d ", priority[i]);
printf(" %d ", ct[i]);
printf(" %d ", tat[i]);
printf(" %d\n", wt[i]);
}
}

// If no process is present, display message


if (!isPresent) {
printf("No processes present.\n");
return;
}

float avg_wt = (float) total_wt / n;


float avg_tat = (float) total_tat / n;
printf("Average waiting time = %f\n", avg_wt);
printf("Average turn around time = %f\n", avg_tat);
}

// Driver code
int main() {
int n;

// Input number of processes


printf("Enter number of processes: ");
scanf("%d", &n);

int processes[n];
int burst_time[n];
int arrival_time[n];
int priority[n];
// Input burst time, arrival time, and priority for each process
for (int i = 0; i < n; i++) {
processes[i] = i + 1; // Process IDs
printf("Enter burst time for process %d: ", i + 1);
scanf("%d", &burst_time[i]);
printf("Enter arrival time for process %d: ", i + 1);
scanf("%d", &arrival_time[i]);
printf("Enter priority for process %d: ", i + 1);
scanf("%d", &priority[i]);
}
// Calculate average waiting time and average turn-around time 25
findavgTime(processes, n, burst_time, arrival_time, priority);
return 0;
}

Output: -
26

Program 5
Aim: - Implementation of CPU Scheduling. (i) Round Robin (ii) Longest Job First.

Theory: -
Round Robin Algorithm

DESCRIPTION: - The process that arrives first is executed first with a proper Time Quantum.

Algorithm: -
1. Initialize Variables:
• Declare arrays for process IDs, burst times, arrival times, completion times, turn-around times,
and waiting times.
• Initialize variables for quantum (time slice), current time, and completed process count.
2. Input Number of Processes:
• Prompt the user for the number of processes (n) and store it.
3. Input Burst Time and Arrival Time for Each Process:
• For each process, get burst time and arrival time from the user.
4. Round Robin Execution:
• Set up a queue to manage the processes awaiting execution.
• Initialize a timer to track elapsed time.
• Iterate until all processes are completed:
o Select a process from the front of the queue.
o Execute the process for a fixed quantum time.
o Update the current time and reduce the burst time of the process accordingly.
o If the process completes within the quantum:
▪ Calculate its completion time, turn-around time, and waiting time.
▪ Move it to the completed queue.
o If the process does not complete within the quantum:
▪ Move it to the end of the queue to allow other processes to execute.
o Repeat until all processes are executed.
5. Display Process Details:
• Print process ID, burst time, arrival time, completion time, turn-around time, and waiting time
for each process.
6. Calculate and Display Averages:
• Calculate the average waiting time and average turn-around time based on completed processes.
• Print these averages to summarize the performance of the Round Robin scheduling algorithm.

Code: -
#include <stdio.h>

// Function to find completion time, turn-around time, and waiting time for all processes
void findCT_TAT_WT(int processes[], int n, int bt[], int at[], int ct[], int tat[], int wt[], int quantum) {
int rt[n];

// Initialize remaining time to burst time


for (int i = 0; i < n; i++) {
rt[i] = bt[i];
}
int currentTime = 0; 27
int completed = 0;

while (completed != n) {
int done = 1;

for (int i = 0; i < n; i++) {


if (rt[i] > 0) {
done = 0;

if (rt[i] > quantum) {


currentTime += quantum;
rt[i] -= quantum;
} else {
currentTime += rt[i];
ct[i] = currentTime;
rt[i] = 0;
completed++;

// Calculate turn-around time


tat[i] = ct[i] - at[i];

// Calculate waiting time


wt[i] = tat[i] - bt[i];
}
}
}

if (done == 1) {
break;
}
}
}

// Function to calculate average time


void findavgTime(int processes[], int n, int bt[], int at[], int quantum) {
int ct[n], tat[n], wt[n];
int total_wt = 0, total_tat = 0;

// Find completion time, turn-around time, and waiting time for all processes
findCT_TAT_WT(processes, n, bt, at, ct, tat, wt, quantum);

// Display processes along with all details


printf("Processes Burst time Arrival time Completion time Turn around time Waiting time\n");
for (int i = 0; i < n; i++) {
total_wt += wt[i];
total_tat += tat[i];
printf(" %d ", processes[i]);
printf(" %d ", bt[i]);
printf(" %d ", at[i]);
printf(" %d ", ct[i]);
printf(" %d ", tat[i]);
printf(" %d\n", wt[i]);
}
float avg_wt = (float)total_wt / n; 28
float avg_tat = (float)total_tat / n;
printf("Average waiting time = %f\n", avg_wt);
printf("Average turn-around time = %f\n", avg_tat);
}

// Driver code
int main() {
int n, quantum;

// Input number of processes


printf("Enter number of processes: ");
scanf("%d", &n);

int processes[n];
int burst_time[n];
int arrival_time[n];

// Input burst time and arrival time for each process


for (int i = 0; i < n; i++) {
processes[i] = i + 1; // Process IDs
printf("Enter burst time for process %d: ", i + 1);
scanf("%d", &burst_time[i]);
printf("Enter arrival time for process %d: ", i + 1);
scanf("%d", &arrival_time[i]);
}

// Input quantum time


printf("Enter quantum time: ");
scanf("%d", &quantum);

// Calculate average waiting time and average turn-around time


findavgTime(processes, n, burst_time, arrival_time, quantum);
return 0;
}
Output: -
29
LJF Algorithm

DESCRIPTION: - The job which has longest burst time is executed first.

Algorithm: -
1. Initialize Variables:
• Declare arrays for process IDs, burst times, arrival times, completion times, turn-around times,
and waiting times.
• Initialize variables for current time, completed process count, and any other necessary tracking
variables.
2. Input Number of Processes:
• Prompt the user for the number of processes (n) and store it.
3. Input Burst Time and Arrival Time for Each Process:
• For each process, get burst time and arrival time from the user.
4. Sort Processes by Burst Time (Longest Job First):
• Implement a sorting function to arrange processes in descending order based on their burst times.
5. Calculate Completion Time, Turn-Around Time, and Waiting Time:
• Initialize a timer for tracking current time.
• Iterate through the sorted list of processes:
o Select the process with the longest burst time.
o Execute the process to completion.
o Update current time and calculate its completion time, turn-around time, and waiting time.
o Move to the next process and repeat until all processes are completed.
6. Display Process Details:
• Print process ID, burst time, arrival time, completion time, turn-around time, and waiting time
for each process.
7. Calculate and Display Averages:
• Calculate the average waiting time and average turn-around time based on completed processes.
• Print these averages to summarize the performance of the LJF scheduling algorithm.

Code: -
#include <stdio.h>
#include <stdbool.h>

// Function to sort processes based on burst time (longest job first)


void sortProcessesByBurstTime(int processes[], int bt[], int at[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (bt[j] < bt[j + 1]) {
// Swap process details
int temp = processes[j];
processes[j] = processes[j + 1];
processes[j + 1] = temp;

temp = bt[j];
bt[j] = bt[j + 1];
bt[j + 1] = temp;

temp = at[j];
at[j] = at[j + 1];
at[j + 1] = temp;
}
}
} 30
}

// Function to find completion time, turn-around time, and waiting time for all processes
void findCT_TAT_WT(int processes[], int n, int bt[], int at[], int ct[], int tat[], int wt[]) {
int currentTime = 0;

for (int i = 0; i < n; i++) {


if (currentTime < at[i]) {
currentTime = at[i];
}
ct[i] = currentTime + bt[i];
currentTime = ct[i];
tat[i] = ct[i] - at[i];
wt[i] = tat[i] - bt[i];
}
}

// Function to calculate average time


void findavgTime(int processes[], int n, int bt[], int at[]) {
int ct[n], tat[n], wt[n];
int total_wt = 0, total_tat = 0;
bool isPresent = false;

// Sort processes by burst time (longest job first)


sortProcessesByBurstTime(processes, bt, at, n);

// Find completion time, turn-around time, and waiting time for all processes
findCT_TAT_WT(processes, n, bt, at, ct, tat, wt);

// Display processes along with all details


printf("Processes Burst time Arrival time Completion time Turn around time Waiting time\n");
for (int i = 0; i < n; i++) {
// Check if process is present based on arrival time
if (ct[i] != 0) {
isPresent = true;
total_wt += wt[i];
total_tat += tat[i];
printf(" %d ", processes[i]);
printf(" %d ", bt[i]);
printf(" %d ", at[i]);
printf(" %d ", ct[i]);
printf(" %d ", tat[i]);
printf(" %d\n", wt[i]);
}
}

// If no process is present, display message


if (!isPresent) {
printf("No processes present.\n");
return;
}
float avg_wt = (float) total_wt / n;
float avg_tat = (float) total_tat / n;
printf("Average waiting time = %f\n", avg_wt);
printf("Average turn around time = %f\n", avg_tat);
} 31

// Driver code
int main() {
int n;

// Input number of processes


printf("Enter number of processes: ");
scanf("%d", &n);

int processes[n];
int burst_time[n];
int arrival_time[n];

// Input burst time and arrival time for each process


for (int i = 0; i < n; i++) {
processes[i] = i + 1; // Process IDs
printf("Enter burst time for process %d: ", i + 1);
scanf("%d", &burst_time[i]);
printf("Enter arrival time for process %d: ", i + 1);
scanf("%d", &arrival_time[i]);
}

// Calculate average waiting time and average turn-around time


findavgTime(processes, n, burst_time, arrival_time);
return 0;
}

Output: -
32

Program 6
Aim: - Implementation of Process and thread (Life cycle of process): (i) Process
creation and Termination; (ii) Thread creation and Termination.

Theory: -
Process creation and Termination

DESCRIPTION: -The process creation and termination in operating systems involve


spawning a new process from an existing process and managing its life cycle until completion.
This typically includes creating a child process using fork() in Unix-like systems, performing
some tasks, and eventually terminating either normally or abnormally.

Algorithm: -
1. Create a Child Process:
• Use the fork() system call to create a new process.
• Upon successful creation, fork() returns a non-negative value (child PID) to the parent process
and 0 to the child process.
• If fork() fails, it returns a negative value indicating an error.
2. Child Process Execution:
• In the child process (identified by fork() returning 0), perform specific tasks unique to the child's
execution context.
• This may involve computations, I/O operations, or any other tasks required by the application.
3. Parent Process Handling:
• In the parent process, after fork() succeeds, it typically continues its own execution or waits for
the child process to complete using wait() or waitpid() system calls.
• wait() or waitpid() allows the parent to synchronize with the termination of the child process and
retrieve its termination status.
4. Termination of Processes:
• Both parent and child processes may terminate explicitly using exit() system call, indicating
successful completion or abnormal termination with an exit status.
• The termination status can be retrieved by the parent process using wait() or waitpid().
5. Cleanup and Resource Release:
• After the child process terminates, the parent process should release any resources associated with
the child process and continue its execution or terminate based on application logic.

Code: -
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
pid_t pid;

// Create a child process


pid = fork();
if (pid < 0) { 33
// Fork failed
fprintf(stderr, "Process creation failed\n");
return 1;
} else if (pid == 0) {
// Child process
printf("Child process created with PID: %d\n", getpid());
// Simulate some work
printf("Child process is doing some work...\n");
sleep(2); // Simulating work with sleep
printf("Child process completed.\n");
exit(0); // Terminate child process
} else {
// Parent process
printf("Parent process with PID: %d\n", getpid());
printf("Waiting for child process to complete...\n");
wait(NULL); // Wait for child process to terminate
printf("Child process terminated. Parent exiting.\n");
}

return 0;
}

Output: -
34
Thread creation and Termination

DESCRIPTION: - Threads are lightweight processes within a process that share resources
such as memory and file descriptors. Thread creation and termination involve spawning new
threads, executing concurrent tasks within the same process, and managing their life cycle
until completion.

Algorithm: -
1. Create a Thread:
• Use the pthread_create() function to create a new thread within the current process.
• Provide the necessary arguments such as thread attributes and a function pointer to the function
that the thread will execute.
2. Thread Function Execution:
• Define a function that will be executed by the newly created thread (pthread_create() takes this
function pointer as an argument).
• This function performs the specific tasks or computations that the thread is responsible for.
3. Main Thread Handling:
• In the main thread of execution, after pthread_create() successfully creates a thread, it can
continue its own tasks or synchronize with the newly created thread using pthread_join().
4. Wait for Thread Completion:
• Use pthread_join() to wait for the thread to complete its execution. This function blocks the
main thread until the specified thread terminates.
• pthread_join() also optionally retrieves the exit status of the thread upon termination.
5. Thread Termination:
• Inside the thread function, terminate the thread's execution by calling pthread_exit() with a
return value.
• The return value of pthread_exit() can be retrieved by the thread that joined it using
pthread_join().
6. Cleanup and Resource Management:
• After a thread completes its execution, any resources it acquired (e.g., allocated memory) should
be properly released to avoid memory leaks or resource contention.

Code: -
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

void *thread_function(void *arg) {


printf("Thread created. Performing some work...\n");
sleep(2); // Simulate work
printf("Thread completed.\n");
pthread_exit(NULL);
}

int main() {
pthread_t thread;
int ret;
printf("Main thread started.\n");
// Create thread
ret = pthread_create(&thread, NULL, thread_function, NULL);
if (ret) {
fprintf(stderr, "Error: pthread_create() failed\n"); 35
return 1;
}

// Wait for thread to finish


pthread_join(thread, NULL);

printf("Thread joined. Main thread exiting.\n");

return 0;
}

Output: -
36

Program 7
Aim: - Implementation of Producer-Consumer Problem using Semaphores and
Reader Writer Problem

Theory: -
Producer-Consumer Problem

DESCRIPTION: - The Producer-Consumer problem involves synchronization between


producer threads that add items to a buffer and consumer threads that remove items from the
buffer. Semaphores are used to manage access to the buffer and to coordinate the producers
and consumers.

Algorithm: -
1. Initialize Semaphores and Shared Buffer:
• Use semaphores to manage the synchronization:
o empty semaphore initialized to the buffer size (number of empty slots).
o full semaphore initialized to 0 (no items in the buffer initially).
o mutex semaphore for mutual exclusion.
2. Producer Thread:
• Wait on empty (decrement if a slot is available).
• Wait on mutex to enter the critical section.
• Add an item to the buffer.
• Signal (increment) mutex.
• Signal full (indicate an item is available).
3. Consumer Thread:
• Wait on full (decrement if an item is available).
• Wait on mutex to enter the critical section.
• Remove an item from the buffer.
• Signal (increment) mutex.
• Signal empty (indicate an empty slot is available).
Code: -
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define BUFFER_SIZE 10

int buffer[BUFFER_SIZE];
int in = 0, out = 0;
sem_t empty, full, mutex;

void *producer(void *param) {


int item;
while (1) { 37
item = rand() % 100; // Produce an item
sem_wait(&empty); // Wait for an empty slot
sem_wait(&mutex); // Enter critical section

buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
printf("Produced: %d\n", item);

sem_post(&mutex); // Exit critical section


sem_post(&full); // Signal that an item is available

sleep(1);
}
}

void *consumer(void *param) {


int item;
while (1) {
sem_wait(&full); // Wait for an item
sem_wait(&mutex); // Enter critical section

item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
printf("Consumed: %d\n", item);

sem_post(&mutex); // Exit critical section


sem_post(&empty); // Signal that a slot is empty

sleep(1);
}
}

int main() {
pthread_t prod_tid, cons_tid;

// Initialize semaphores
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
sem_init(&mutex, 0, 1);

// Create producer and consumer threads


pthread_create(&prod_tid, NULL, producer, NULL);
pthread_create(&cons_tid, NULL, consumer, NULL);

// Join threads (though in an infinite loop, this never happens)


pthread_join(prod_tid, NULL);
pthread_join(cons_tid, NULL);

// Destroy semaphores
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);

return 0;
}
38
Output: -

Reader Writer Problem

DESCRIPTION: - The Reader-Writer problem ensures that multiple readers can access the
shared resource simultaneously, but writers require exclusive access to the resource.
Semaphores are used to manage access and maintain the synchronization between readers and
writers.
Algorithm: -
1. Initialize Semaphores and Variables:
• rw_mutex semaphore for writer access (initialized to 1).
• mutex semaphore for reader count access (initialized to 1).
• read_count to track the number of readers.
2. Reader Thread:
• Wait on mutex to enter the critical section to update read_count.
• If the reader is the first one, wait on rw_mutex to block writers.
• Increment read_count.
• Signal mutex to exit the critical section.
• Read the shared resource.
• Wait on mutex to enter the critical section to update read_count.
• If the reader is the last one, signal rw_mutex to allow writers.
• Decrement read_count.
• Signal mutex to exit the critical section.
3. Writer Thread:
• Wait on rw_mutex to enter the critical section (block other readers and writers).
• Write to the shared resource.
• Signal rw_mutex to exit the critical section (allow readers and writers).
Code: - 39
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

sem_t rw_mutex, mutex;


int read_count = 0;

void *reader(void *param) {


while (1) {
sem_wait(&mutex); // Enter critical section to update read_count
read_count++;
if (read_count == 1) {
sem_wait(&rw_mutex); // If first reader, lock rw_mutex
}
sem_post(&mutex); // Exit critical section

// Reading section
printf("Reader is reading\n");
sleep(1);

sem_wait(&mutex); // Enter critical section to update read_count


read_count--;
if (read_count == 0) {
sem_post(&rw_mutex); // If last reader, unlock rw_mutex
}
sem_post(&mutex); // Exit critical section

sleep(1);
}
}

void *writer(void *param) {


while (1) {
sem_wait(&rw_mutex); // Enter critical section (block readers)

// Writing section
printf("Writer is writing\n");
sleep(1);

sem_post(&rw_mutex); // Exit critical section (unblock readers)


sleep(1);
}
}

int main() {
pthread_t rtid1, rtid2, wtid;

// Initialize semaphores
sem_init(&rw_mutex, 0, 1);
sem_init(&mutex, 0, 1);
// Create reader and writer threads 40
pthread_create(&rtid1, NULL, reader, NULL);
pthread_create(&rtid2, NULL, reader, NULL);
pthread_create(&wtid, NULL, writer, NULL);

// Join threads (though in an infinite loop, this never happens)


pthread_join(rtid1, NULL);
pthread_join(rtid2, NULL);
pthread_join(wtid, NULL);

// Destroy semaphores
sem_destroy(&rw_mutex);
sem_destroy(&mutex);

return 0;
}

Output: -

You might also like