0% found this document useful (0 votes)
2 views49 pages

OS Lab File

The document is a practical file from the Faculty of Technology at the University of Delhi, authored by Hitesh Purohit, detailing various practical exercises related to operating systems. It covers the evolution of operating systems, a study of Windows 11 with comparative analysis against Ubuntu and macOS, basic DOS commands, and the implementation of scheduling algorithms. The document aims to enhance understanding of operating systems' design principles, functionality, and user interaction.

Uploaded by

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

OS Lab File

The document is a practical file from the Faculty of Technology at the University of Delhi, authored by Hitesh Purohit, detailing various practical exercises related to operating systems. It covers the evolution of operating systems, a study of Windows 11 with comparative analysis against Ubuntu and macOS, basic DOS commands, and the implementation of scheduling algorithms. The document aims to enhance understanding of operating systems' design principles, functionality, and user interaction.

Uploaded by

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

OPERATING SYSTEM

PRACTICAL FILE
FACULTY OF TECHNOLOGY
UNIVERSITY OF DELHI

SUBMITTED BY:
HITESH PUROHIT
ROLL NO.: 24293916083
BATCH: CSE-A

SUBMITTED TO:
MRS. GEETANJALI BHOLA
FACULTY OF TECHNOLOGY
UNIVERSITY OF DELHI
INDEX
SL
PRACTICAL TITLE DATE SIGN
NO.
1 Evolution and Pipeline of Operating System
Study of One Modern Operating System and
2
Comparative Analysis
Study of Basic DOS Commands in Command
3
Prompt
4 Process and Thread Management in Linux

Implementation of FCFS (First Come First


5
Serve) Scheduling Algorithm

Implementation of SJF Scheduling


6
(Preemptive and Non-Preemptive)
Implementation of Priority Scheduling
7
(Preemptive and Non-Preemptive)
Implementation of Round Robin (RR)
8
Scheduling Algorithm
Practical 1 :-
Evolution and Pipeline of Operating System

Aim
The aim of this practical is to study the historical evolution of Operating
Systems and to understand how an Operating System works internally through
its processing pipeline.

Introduction
An Operating System (OS) is system software that acts as an intermediary
between the computer user and the hardware. Every program that runs on a
computer depends on the operating system to access memory, CPU time,
storage, and input/output devices. Without an OS, the user would have to
directly control hardware, which is complex and inefficient.
Modern operating systems such as Microsoft Windows, Linux, macOS and UNIX
provide a stable and secure environment where applications can run smoothly.
They manage processes, memory, files, devices, and ensure that multiple users
or programs can work simultaneously without conflict.
Over time, operating systems have evolved significantly. The journey from
machines with no operating system to today's intelligent, multitasking systems
reflects the rapid development of computer science.

Evolution of Operating Systems


First Generation (1940–1955): No Operating System
During the first generation of computers, there was no operating system. These
machines used vacuum tubes and were extremely large, expensive, and power-
consuming. Programs were written in machine language and executed directly
on hardware.
Users had to manually control the computer using switches, plugboards, and
punched cards. Each program was loaded and run one at a time, and the
programmer was responsible for all operations such as input/output control
and memory usage.
Due to the absence of an operating system, there was no scheduling, error
handling, or multitasking, making the process slow and inefficient. This
generation laid the foundation for the development of operating systems by
highlighting the need for automation and better resource management.

Second Generation (1955–1965): Batch Operating Systems


In the second generation of computers, batch operating systems were
introduced to improve system efficiency. Computers used transistors instead of
vacuum tubes, making them more reliable and faster. Jobs with similar
requirements were grouped together into batches and executed sequentially
without user interaction.
Programs were written in assembly language and early high-level languages like
FORTRAN and COBOL. The operating system used a resident monitor to
manage job sequencing, loading, and execution. Input was provided using
punched cards, and output was generated on printers.
Although batch systems improved CPU utilization, they had limitations such as
long turnaround time and lack of user interaction. However, this generation
marked the beginning of automated job control and operating system
development.

Third Generation (1965–1980): Multiprogramming and Time-Sharing


The third generation of computers introduced multiprogramming and time-
sharing operating systems to improve system performance and user
interaction. Computers used integrated circuits (ICs), making them smaller,
faster, and more reliable.
In multiprogramming, multiple programs were kept in main memory at the
same time, allowing the CPU to switch between them when one program
was waiting for input/output. This significantly increased CPU utilization.
Time-sharing systems enabled multiple users to interact with the computer
simultaneously by allocating small time slices of the CPU to each user.
Operating systems in this generation provided features such as process
scheduling, memory management, and file systems. These advancements
made computers more accessible and efficient, paving the way for modern
multi-user operating systems.

Fourth Generation (1980–Present): Modern Operating Systems


The fourth generation marks the development of modern operating systems
with the advent of microprocessors and personal computers. Operating
systems became more user-friendly, efficient, and powerful. This era
introduced graphical user interfaces (GUI), multitasking, and networking
capabilities.
Modern operating systems support multitasking, multi-user environments,
virtual memory, security mechanisms, and device independence. Examples
include Microsoft Windows, Linux, and macOS. These systems efficiently
manage hardware resources while providing a stable and interactive
environment for users.
Advancements such as distributed systems, cloud computing support, and
real-time processing have further enhanced the role of operating systems,
making them an essential part of modern computing.
Pipeline of Operating System
The pipeline of an operating system refers to the sequence of steps that occur
when a user performs an action and the system processes that request.
Basic Structure of an Operating System
An operating system is generally structured in layers:
1. User — The person interacting with the system.
2. Application Programs — Software used by the user (e.g., text editor,
browser).
3. System Call Interface — Allows programs to request services from the
OS.
4. Kernel — The core component of the OS that manages all resources.
5. Hardware — The physical components of the computer.
This layered approach ensures abstraction. Users and applications do not
interact directly with hardware. Instead, the operating system manages and
controls all hardware operations.

Working Pipeline
When a user performs an action, such as opening a file, the process follows a
structured path:
1. The user interacts with an application, for example, a text editor.
2. The application interprets the user's request and generates a system
call, such as a request to read a file from storage.
3. The system call transfers control from user mode to kernel mode.
4. The kernel then checks permissions, locates the file in the file system,
allocates memory buffers, and communicates with the device driver
responsible for the storage device.
5. The device driver interacts with the hardware controller, which retrieves
the requested data from disk.
6. Once the data is fetched, it travels back through the same path —
hardware → kernel → application → user.
This entire process happens in milliseconds, giving the user a smooth
experience.

Internal Components of the Operating System


Internally, the operating system consists of several major components working
together:
1. Process Management Responsible for creating, scheduling, and terminating
processes. It ensures fair CPU allocation and prevents conflicts between
processes.
2. Memory Management Controls the allocation and deallocation of RAM.
Techniques such as paging and segmentation are used to efficiently utilize
memory and prevent one process from interfering with another.
3. File System Management Organizes data into files and directories. It
provides a logical structure for storing and retrieving information.
4. Device Management Handles communication with input and output devices
through device drivers. It ensures that hardware devices function properly
without requiring applications to understand hardware-level details.
Figure : Pipe() system call

Conclusion
This practical provided a clear understanding of the historical evolution of
operating systems from early computer systems to modern platforms. It also
helped in learning how an operating system works internally through its
processing pipeline, including job management, process scheduling, memory
allocation, and input/output handling. Overall, the practical highlighted the
important role of operating systems in improving system efficiency, resource
utilization, and user interaction.
Practical 2 :-
Study of One Modern Operating System and Comparative Analysis

Aim
The aim of this practical is to study a modern operating system in detail and
perform a comparative analysis with other widely used operating systems
based on architecture, features, performance, security, and usability.

Introduction
An operating system (OS) is the core system software that controls the overall
functioning of a computer. It acts as an intermediary between computer
hardware and application software, ensuring efficient resource utilization and
smooth user interaction. Modern operating systems are highly advanced and
provide support for multitasking, networking, security frameworks,
virtualization technologies, and graphical user interfaces.
In this practical, Windows 11 has been chosen for detailed study as it is one of
the most widely used desktop operating systems today. It represents the latest
stage in the evolution of operating systems developed by Microsoft.
For comparison, Ubuntu, a popular Linux-based operating system, and macOS,
used in computers manufactured by Apple, are also analysed.
Study of Windows 11
Windows 11 is the most recent major version of the Windows NT operating
system series. It offers an updated graphical interface, stronger security
mechanisms, and optimized system performance. The operating system is
designed to function efficiently on desktops, laptops, and professional
workstations.

System Architecture
Windows 11 is built on a hybrid kernel architecture derived from the Windows
NT design. This architecture integrates characteristics of both monolithic and
microkernel models.
The architecture is divided into two primary modes:
• User Mode — Runs user applications and system-level services.
• Kernel Mode — Handles critical components such as the kernel, device
drivers, memory management, and CPU scheduling.
This separation enhances system reliability and security by preventing user-
level programs from directly interacting with hardware.
Major Features
Windows 11 introduces multiple modern enhancements:
• Supports efficient multitasking through features such as Snap Layouts,
enabling better window management.
• Includes built-in security tools like Windows Defender, Secure Boot, and
TPM (Trusted Platform Module) support.
• Provides virtualization capabilities through Hyper-V.
• Seamless cloud integration using Microsoft OneDrive.
• Broad hardware and software compatibility makes Windows 11 suitable
for both individual users and enterprise environments.

Process and Memory Management


Windows 11 implements virtual memory management using paging
techniques. Each process is allocated a separate virtual address space, ensuring
isolation and system stability.
The CPU scheduler follows a priority-based pre-emptive scheduling approach,
allowing higher-priority processes to interrupt lower-priority ones, thereby
maintaining system responsiveness.

File System Support


The primary file system used by Windows 11 is NTFS (New Technology File
System), which offers:
• Advanced file security and access permissions
• File and disk encryption
• Disk quota management
• Support for large files and volumes

Comparative Analysis
The operating systems compared in this study are:
• Windows 11
• Ubuntu
• macOS

Architectural Differences
• Windows 11 employs a hybrid kernel structure.
• Ubuntu uses the Linux kernel, which follows a monolithic architecture
with loadable modules.
• macOS is based on the XNU kernel, combining Mach microkernel
features with BSD components.
While Windows and macOS adopt hybrid designs, Linux emphasizes monolithic
architecture with flexibility through modularity.

User Interface Design


• Windows 11 features a modern, visually appealing interface with a
centred taskbar and redesigned Start menu.
• Ubuntu generally uses the GNOME desktop environment, known for its
simplicity and high level of customization.
• macOS provides a consistent and polished interface, prioritizing ease of
use and visual clarity.
Windows is commonly used in corporate and academic environments, Ubuntu
is favoured by developers and system administrators, and macOS is popular
among creative professionals.

Security Mechanisms
• Windows 11 offers integrated security tools such as Windows Defender,
BitLocker encryption, and mandatory TPM 2.0 support.
• Ubuntu benefits from a strong permission-based security model and
open-source transparency, reducing vulnerability to malware.
• macOS provides robust UNIX-based security, application sandboxing, and
Gatekeeper for application verification.

Performance Considerations
• Ubuntu is lightweight and performs efficiently on low-end systems.
• Windows 11 requires comparatively higher hardware specifications.
• macOS is highly optimized for Apple hardware, resulting in stable and
smooth performance within its ecosystem.

Software Support
• Windows 11 supports the widest range of commercial software and
games.
• Ubuntu primarily supports open-source applications and can run
Windows programs using compatibility tools like Wine.
• macOS supports high-end professional software but offers limited
gaming support.

Conclusion
This practical enhanced the understanding of modern operating system design
principles and demonstrated how different operating systems adopt varied
approaches to achieve performance, security, and usability. Windows 11 stands
out for its broad compatibility and rich feature set, Ubuntu excels in lightweight
performance and developer-friendliness, while macOS offers a seamless
experience within the Apple ecosystem. The study emphasizes the crucial role
of operating systems in ensuring efficient and reliable computing.
Practical 3 :- BASIC COMMAND PROMPT COMMANDS

File & Directory Operations

[Link] a file

Syntax: copy con text_file_os.txt

Explanation: This command redirects your keyboard input directly into a new file.
After typing your content, press Ctrl+Z and then Enter to save and exit.

2. Listing Only .pdf Files

Syntax: dir *.pdf


Explanation: Uses the dir command combined with a wildcard (*) to filter the results.
It will display only files ending with the .pdf extension in the current folder.

3. Sorting Files (Smallest to Largest)

Syntax: dir /OS

Explanation: The /O switch stands for "Order," and adding S tells CMD to sort by size.
It lists files starting from the smallest byte size up to the largest.

4. Moving a File

Syntax: move "source_path" "destination_path"

Explanation: This command transfers a file from its original folder to a new location.
If the destination folder doesn't exist, it will result in an error or rename the file.

5. Renaming a File

Syntax: ren "[Link]" "[Link]"

Explanation: Short for "rename," this command changes the label of a file without
altering its contents. Both the old name and the new name must be provided in the
command.
6. Changing a Directory

Syntax: cd folder_name

Explanation: Standing for "Change Directory," this allows you to navigate into
subfolders. To go back up one level toward the root, you would use cd ...

7. Deleting a File

Syntax: del [Link]

Explanation: This permanently removes the specified file from the directory. Be
careful, as files deleted via CMD usually bypass the Recycle Bin.

System & Info Commands


8. Use of echo

Syntax: echo Your Message

Explanation: This command prints text strings to the command line or can be used to
toggle command masking (echo off). It is commonly used in batch scripts to provide
status updates to the user.
9. System Information

Syntax: systeminfo
Explanation: This tool retrieves and displays detailed configuration data about your
OS and hardware. It includes info like BIOS version, RAM capacity, and network card
details.

10. Print Working Directory (pwd)

Syntax: cd (by itself)

Explanation: While Linux uses pwd, Windows uses the cd command without any
arguments to display the current path. The path is also usually visible in the
command prompt's blinker/cursor line.

C++ & Command Line Arguments


11. Compiling and Running with Arguments

Syntax: g++ [Link] -o [Link] --- then--- [Link] arg1 arg2

Explanation: The first command compiles your source code into an executable file.
The second command runs that file while passing extra data (arguments) directly into
the main function.
Practical 4 :-
Process creation and its properties

Aim
To implement the First Come First Served (FCFS) scheduling algorithm using a
menu-driven C program that takes process details (arrival time and CPU burst
time) and allows the user to choose between the input sequence or a custom
sequence for execution.

Theory
Process
A process is a program in execution. It has its own memory space and
resources. Each process has a unique PID (Process ID) and a PPID (Parent
Process ID). Other attributes include CPU usage, memory usage, and process
state.
Thread
A thread is the smallest unit of execution within a process. Multiple threads
within a process share the same memory space. Each thread has its own
Thread ID (TID), program counter, and stack.
fork() System Call
fork() is used to create a new process in Linux. When called:
• A child process is created as a copy of the parent.
• Returns 0 in child process.
• Returns Child PID in parent process.
• Returns -1 if creation fails.
Extracting Process Attributes
Process attributes in Linux can be viewed using:
• ps — snapshot of running processes.
• top / htop — real-time process monitoring.
• /proc directory — contains detailed info of each process.
pthread (POSIX Threads)
Threads are created using the pthread library. Key functions:
• pthread_create() — creates a new thread.
• pthread_join() — waits for thread to finish.
• pthread_self() — returns Thread ID.

Introduction
A process is a program in execution. It is not only the program code but also
includes resources such as memory, CPU registers, and I/O devices. Processes
are the fundamental unit of work in an operating system, and their
management is crucial for multitasking and resource allocation.

Process Control Block (PCB)


The operating system maintains a data structure called the Process Control
Block (PCB) for each process. The PCB contains all the information required to
manage the process, such as process ID (PID), parent process ID (PPID), process
state, program counter, CPU register values, memory management details,
scheduling priority, and I/O status. This information allows the operating
system to suspend and resume processes correctly.

Process Creation using fork()


The fork() system call in UNIX/Linux is used to create a new process. When a
process calls fork(), the operating system generates a child process that is a
duplicate of the parent. Both processes continue execution from the point of
the fork() call.
• In the parent process, fork() returns the PID of the child.

• In the child process, fork() returns 0.

• If fork() fails, it returns a negative value.


This mechanism demonstrates how the operating system enables concurrent
execution of multiple processes.
Threads and Their Identification
Threads are smaller units of execution within a process. Unlike processes,
threads share the same memory space but maintain separate stacks and
registers. In Linux, threads can be created using pthread_create(). Each process
and thread has a unique identifier:
• getpid() returns the process ID.

• getppid() returns the parent process ID.

• pthread_self() returns the thread ID.


Printing these identifiers helps in understanding the hierarchy and relationship
between processes and threads.

Process Explorer Software


On Windows systems, Process Explorer is a powerful tool for studying process
and thread management. It provides a graphical interface that displays
processes in a hierarchical tree structure along with their child processes.
Process Explorer allows users to:
• View thread details such as IDs, CPU usage, and start addresses.

• Monitor DLLs loaded by a process.

• Observe thread states such as running or waiting.

• Track resource consumption at a granular level.

• Suspend, resume, or terminate threads for debugging purposes.

Algorithm
1. Start the program.
2. Print the PID of the parent process.
3. Call fork() to create a child process.
4. If fork() fails, print an error message.
5. If fork() returns 0, execute the child process block: print child PID and
parent PID, then create a thread using pthread_create() and print its
thread ID.
6. If fork() returns a positive value, execute the parent process block: print
parent PID and child PID, then create a thread using pthread_create()
and print its thread ID.
7. End the program.

Program
P1 : Process Creation using fork()
Code:

Output

P2: Process Control Block (PCB) Attributes Program


Code:

Output:

P3: Thread Creation using pthread


Code
Output:

Process Explorer Observation


Process Explorer tool was installed and executed.
Different running processes were observed in hierarchical form.
By opening the Threads tab of a process, multiple thread IDs and their CPU
usage were observed.
1. One process can contain multiple threads.
2. Each thread has a unique Thread ID.
3. Threads share the same process resources.
4. Process Explorer shows real-time thread information.
Observation:
1. One process can have multiple threads.
2. Each thread has unique ID.

Conclusion
This practical demonstrates the fundamental concepts of process creation and
management. By using fork() to create child processes, extracting PCB
attributes through system calls, printing process and thread IDs, and exploring
thread management with Process Explorer, one gains a comprehensive
understanding of how operating systems handle multitasking. This knowledge
is essential for appreciating the complexity of scheduling, resource allocation,
and thread management in modern computing environments.
Practical 5 :-
Aim
To implement the First Come First Served (FCFS) scheduling algorithm using a
menu-driven C program that takes process details (arrival time and CPU burst
time) and allows the user to choose between the input sequence or a custom
sequence for execution.

Theory
Scheduling is the method by which processes are selected for execution by the
CPU. The First Come First Served (FCFS) scheduling algorithm is one of the
simplest scheduling techniques. In FCFS, the process that arrives first in the
ready queue is executed first. It is a non-preemptive scheduling algorithm,
meaning once a process starts execution, it runs until completion.
The key parameters in scheduling are:
• Arrival Time (AT): The time when a process enters the ready queue.

• Burst Time (BT): The total CPU time required by the process.

• Waiting Time (WT): The time a process spends waiting in the ready
queue before execution.

• Turnaround Time (TAT): The total time taken from process arrival to its
completion.
Formulas:
𝑊𝑇 = 𝑆𝑡𝑎𝑟𝑡 𝑇𝑖𝑚𝑒 − 𝐴𝑟𝑟𝑖𝑣𝑎𝑙 𝑇𝑖𝑚𝑒
𝑇𝐴𝑇 = 𝑊𝑇 + 𝐵𝑢𝑟𝑠𝑡 𝑇𝑖𝑚𝑒
FCFS is fair in the sense that processes are executed in the order they arrive,
but it can lead to the convoy effect, where short processes wait for long
processes to finish.

Algorithm
1. Start the program.
2. Input the number of processes.
3. For each process, take arrival time and burst time.
4. Display a menu:
a. Option 1: Execute processes in the order entered.
b. Option 2: Execute processes in a custom sequence entered by the user.

5. Based on the chosen sequence, calculate waiting time and turnaround


time for each process.
6. Display the Gantt chart (timeline of execution).
7. Print the waiting time and turnaround time for each process.
8. Calculate and display average waiting time and average turnaround time.
9. End the program.

Program:
#include <stdio.h>

void fcfs(int n, int pid[], int at[], int bt[])


{
int wt[20], tat[20];
int total_wt = 0, total_tat = 0;

wt[0] = 0;

for(int i = 1; i < n; i++)


wt[i] = wt[i-1] + bt[i-1];

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


tat[i] = wt[i] + bt[i];

printf("\nGantt Chart:\n");
for(int i = 0; i < n; i++)
printf(" P%d |", pid[i]);
printf("\n");
printf("\nProcess\tAT\tBT\tWT\tTAT\n");
for(int i = 0; i < n; i++)
{
printf("P%d\t%d\t%d\t%d\t%d\n",
pid[i], at[i], bt[i], wt[i], tat[i]);

total_wt += wt[i];
total_tat += tat[i];
}

printf("\nAverage Waiting Time = %.2f",


(float)total_wt / n);

printf("\nAverage Turnaround Time = %.2f\n",


(float)total_tat / n);
}

int main()
{
int n, choice;
int pid[20], at[20], bt[20];

printf("Enter number of processes: ");


scanf("%d", &n);

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


{
pid[i] = i + 1;

printf("Arrival Time of P%d: ", pid[i]);


scanf("%d", &at[i]);

printf("Burst Time of P%d: ", pid[i]);


scanf("%d", &bt[i]);
}
while(1)
{
printf("\n--- FCFS MENU ---\n");
printf("1. Execute in Input Order\n");
printf("2. Execute in Custom Order\n");
printf("3. Exit\n");
printf("Enter choice: ");
scanf("%d", &choice);
if(choice == 1)
{
fcfs(n, pid, at, bt);
}
else if(choice == 2)
{
printf("Enter custom order of process numbers:\n");
for(int i = 0; i < n; i++)
scanf("%d", &pid[i]);

fcfs(n, pid, at, bt);


}
else if(choice == 3)
{
return 0;
}
else
{
printf("Invalid Choice!\n");
}
}
}

Output:
Conclusion
This practical demonstrates the implementation of the First Come First Served
(FCFS) scheduling algorithm. By taking process details and allowing the user to
choose between the input sequence or a custom sequence, the program
calculates waiting time, turnaround time, and average values. The Gantt chart
representation helps visualize CPU allocation. This experiment highlights the
simplicity of FCFS scheduling and its fairness, while also showing its limitation
in handling processes with varying burst times due to the convoy effect.
Practical 6 :-
Aim
The aim of this practical is to implement the Shortest Job First (SJF) scheduling
algorithm in both non-preemptive and preemptive modes, and to calculate the
waiting time and turnaround time for the given set of processes.
Introduction:
CPU scheduling is a critical function of an operating system in a
multiprogramming environment. When several processes are waiting in the
ready queue, the scheduler must decide which process should get access to the
CPU.
Shortest Job First (SJF) is a scheduling algorithm that selects the process with
the smallest burst time for execution. The main objective of SJF is to minimize
the average waiting time of processes.
SJF can be implemented in two ways:
• In the non-preemptive version, once a process starts execution, it
continues until it finishes.
• In the preemptive version, also known as Shortest Remaining Time First
(SRTF), the CPU may switch to a new process if it has a shorter remaining
burst time than the currently running process.
Although modern operating systems such as Ubuntu and Windows 11 use
more dynamic and complex scheduling algorithms, SJF remains important for
understanding how optimal scheduling decisions are made.

Theory of Non-Preemp ve SJF:


In non-preemptive SJF scheduling, the scheduler selects the process with the
smallest burst time from the ready queue. Once the CPU is allocated, the
selected process executes completely without interruption. This method
reduces average waiting time compared to FCFS.
However, it may lead to starvation if shorter processes continuously arrive and
longer processes keep waiting. The selection of the next process is based only
on burst time among the processes that have already arrived.
Theory of Preemp ve SJF (SRTF):
In the preemp ve version of SJF, the scheduler always selects the process with
the smallest remaining burst me. If a new process arrives with a burst me
smaller than the remaining me of the currently execu ng process, the CPU is
immediately reassigned to the new process. This improves response me and
further reduces average wai ng me. However, preemp ve SJF increases context
switching and may cause starva on for long processes.

Algorithm Explana on:


For Non-Preemptive SJF: Processes are sorted based on burst time among the
available processes, and execution continues until completion.
For Preemptive SJF (SRTF): At every time unit, the scheduler checks all arrived
processes and selects the one with the smallest remaining burst time. The
remaining time decreases as the process executes. After completion,
turnaround time and waiting time are calculated using standard formulas.

C Program (Non-Preemp ve SJF):


#include <stdio.h>

int main()
{
int n, i, j, temp;
int at[10], bt[10], ct[10], wt[10], tat[10];
int p[10];
float avg_wt = 0, avg_tat = 0;

printf("Enter number of processes: ");


scanf("%d", &n);
for(i = 0; i < n; i++)
{
p[i] = i + 1;
printf("\nProcess %d\n", i + 1);

printf("Arrival Time: ");


scanf("%d", &at[i]);
printf("Burst Time: ");
scanf("%d", &bt[i]);
}
// Sorting processes according to Burst Time (SJF)
for(i = 0; i < n; i++)
{
for(j = i + 1; j < n; j++)
{
if(bt[i] > bt[j])
{
// swap bt
temp = bt[i];
bt[i] = bt[j];
bt[j] = temp;

// swap at
temp = at[i];
at[i] = at[j];
at[j] = temp;

// swap process id
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
// Completion Time
ct[0] = at[0] + bt[0];
for(i = 1; i < n; i++)
{
ct[i] = ct[i-1] + bt[i];
}

// TAT and WT
for(i = 0; i < n; i++)
{
tat[i] = ct[i] - at[i];
wt[i] = tat[i] - bt[i];

avg_wt += wt[i];
avg_tat += tat[i];
}

avg_wt = avg_wt / n;
avg_tat = avg_tat / n;

printf("\nProcess\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",
p[i], at[i], bt[i], ct[i], tat[i], wt[i]);
}

printf("\nAverage Waiting Time = %.2f", avg_wt);


printf("\nAverage Turnaround Time = %.2f\n", avg_tat);

return 0;
}
Output:

Conclusion:
Shortest Job First scheduling is an optimal algorithm in terms of minimizing
average waiting time. The non-preemptive version is simpler and easier to
implement, while the preemptive version provides better responsiveness and
performance. However, both versions may suffer from starvation if longer
processes continuously wait behind shorter ones. Understanding SJF
scheduling provides deeper insight into how operating systems manage CPU
time efficiently and forms a foundation for more advanced scheduling
techniques.
Practical 7 :-

Aim
The aim of this practical is to implement the Priority Scheduling algorithm in
both non-preemptive and preemptive forms, and to calculate waiting time and
turnaround time for a set of processes.

Introduction:
Priority Scheduling is a CPU scheduling technique in which each process is
assigned a priority value. The CPU is allocated to the process with the highest
priority. If two processes have the same priority, they are executed according to
their arrival order.
Priority scheduling is particularly useful in systems where certain tasks are
more important than others. For example, system-level or real-time tasks may
require higher priority than user-level applications. This scheduling concept is
widely used in modern operating systems such as Ubuntu and Windows 11,
where dynamic priority mechanisms ensure responsiveness and fairness.
Priority scheduling can be implemented in two ways:
• Non-Preemptive Priority Scheduling
• Preemptive Priority Scheduling
In this practical, both versions are studied and implemented.

Theory of Non-Preemptive Priority Scheduling


In non-preemptive priority scheduling, when the CPU becomes free, the
process with the highest priority among the available processes is selected.
Once the process starts execution, it continues until completion. The CPU is not
taken away even if a higher priority process arrives later.
The priority value may be defined such that a lower number indicates higher
priority (this assumption is commonly used in academic problems).
This method is simple to implement but may cause starvation of low-priority
processes if high-priority processes keep arriving.
Theory of Preemptive Priority Scheduling
In preemptive priority scheduling, the CPU always executes the highest-priority
process. If a new process arrives with higher priority than the currently running
process, the current process is interrupted, and the CPU is assigned to the new
process.
This version improves responsiveness, especially in interactive or real-time
systems. However, it increases context switching overhead and may cause
starvation of lower priority processes.
To prevent starvation, operating systems use a technique called aging, where
the priority of waiting processes gradually increases over time.

Algorithm Explanation
For Non-Preemptive Priority Scheduling:
1. Enter the number of processes along with their burst time and priority.
2. Sort all processes in ascending order of priority (lower number = higher
priority).
3. The process with the highest priority executes first without interruption.
4. Calculate completion time sequentially.
5. Compute turnaround time and waiting time using standard formulas.
6. Calculate average waiting time and average turnaround time.

For Preemptive Priority Scheduling:


1. At every time unit, check all arrived processes.
2. Select the process with the highest priority (lowest priority number).
3. If a newly arrived process has higher priority than the running process,
preempt the current process.
4. Continue until all processes complete execution.
5. Compute turnaround time and waiting time.

Program :
#include <stdio.h>
struct Process {
int pid;
int at; // arrival time
int bt; // burst time
int pr; // priority
int wt;
int tat;
int ct;
int completed;
};
int main()
{
int n, i, time = 0, completed = 0;
struct Process p[20];
float total_wt = 0, total_tat = 0;
printf("Enter number of processes: ");
scanf("%d", &n);
// Input
for(i = 0; i < n; i++)
{
p[i].pid = i + 1;
printf("\nProcess %d\n", i + 1);
printf("Arrival Time: ");
scanf("%d", &p[i].at);
printf("Burst Time: ");
scanf("%d", &p[i].bt);
printf("Priority: ");
scanf("%d", &p[i].pr);
p[i].completed = 0;
}

// Scheduling
while(completed < n)
{
int idx = -1;
int highest_priority = 999;
for(i = 0; i < n; i++)
{
if(p[i].at <= time && p[i].completed == 0)
{
if(p[i].pr < highest_priority)
{
highest_priority = p[i].pr;
idx = i;
}
}
}
if(idx != -1)
{
time += p[idx].bt;
p[idx].ct = time;
p[idx].tat = p[idx].ct - p[idx].at;
p[idx].wt = p[idx].tat - p[idx].bt;
total_wt += p[idx].wt;
total_tat += p[idx].tat;
p[idx].completed = 1;
completed++;
}
else
{
time++; // CPU idle
}
}
// Output
printf("\nPID\tAT\tBT\tPR\tCT\tTAT\tWT\n");
for(i = 0; i < n; i++)
{
printf("P%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
p[i].pid, p[i].at, p[i].bt, p[i].pr,
p[i].ct, p[i].tat, p[i].wt);
}
printf("\nAverage Waiting Time = %.2f", total_wt / n);
printf("\nAverage Turnaround Time = %.2f\n", total_tat / n);

return 0;
}

Output:

Conclusion:
Priority scheduling allocates CPU based on importance rather than arrival order
or burst time. The non-preemptive version is simpler and suitable for systems
where interruptions are costly. The preemptive version improves
responsiveness but increases complexity and the risk of starvation.
Understanding both versions helps in analyzing how operating systems manage
tasks of different importance levels efficiently.
Practical 8 :-

Aim
The aim of this practical is to implement the Round Robin CPU scheduling
algorithm and calculate the completion time, waiting time, and turnaround
time for a set of processes using a fixed time quantum.

Introduction
Round Robin scheduling is a preemptive CPU scheduling algorithm designed
mainly for time-sharing systems. In such systems, multiple users or processes
share the CPU, and fairness becomes an important factor.
In Round Robin, each process is given a small unit of CPU time called the time
quantum. If the process does not complete within that time, it is preempted
and placed at the end of the ready queue. The CPU then allocates time to the
next process in the queue. This cycle continues until all processes finish
execution.
This method ensures that every process gets a fair share of CPU time. Modern
operating systems such as Ubuntu and Windows 11 use advanced variations of
time-sharing scheduling concepts similar to Round Robin.

Theory of Round Robin Scheduling


Round Robin scheduling works on the principle of a circular queue. All
processes in the ready queue are executed in cyclic order. Each process is
assigned CPU time equal to the time quantum.
• If the burst time of a process is less than or equal to the time quantum,
it finishes execution during its turn.
• If the burst time is greater than the time quantum, the remaining burst
time is updated, and the process is moved to the end of the queue.
The performance of Round Robin heavily depends on the size of the time
quantum:
• If the time quantum is too large, the algorithm behaves like FCFS.
• If it is too small, excessive context switching occurs, which reduces
efficiency.

Algorithm Explanation
1. Enter the number of processes along with their arrival and burst times.
2. Specify the time quantum.
3. Maintain a remaining burst time array for each process.
4. The scheduler moves through the ready queue in circular order.
5. Each process is given CPU time equal to the time quantum.
6. If the remaining burst time becomes zero, completion time is recorded.
7. This cycle continues until all processes finish execution.
8. After completion, turnaround time and waiting time are calculated using
standard formulas.
9. Calculate average waiting time and average turnaround time.

C Program — Round Robin Scheduling


#include <stdio.h>
int main()
{
int n, tq;
int at[20], bt[20], rt[20];
int ct[20], tat[20], wt[20];
int queue[100], front = 0, rear = 0;
int visited[20] = {0};
int time = 0, completed = 0;
float total_wt = 0, total_tat = 0;
printf("Enter number of processes: ");
scanf("%d", &n);
// Input
for(int i = 0; i < n; i++)
{
printf("\nProcess %d\n", i + 1);
printf("Arrival Time: ");
scanf("%d", &at[i]);
printf("Burst Time: ");
scanf("%d", &bt[i]);
rt[i] = bt[i]; // remaining time
}

printf("Enter Time Quantum: ");


scanf("%d", &tq);
// Add first process to queue
queue[rear++] = 0;
visited[0] = 1;
while(completed < n)
{
int idx = queue[front++];
// If process arrives later than current time
if(time < at[idx])
time = at[idx];
// Execute process
if(rt[idx] > tq)
{
time += tq;
rt[idx] -= tq;
}
else
{
time += rt[idx];
rt[idx] = 0;
ct[idx] = time;
completed++;
}
// Add newly arrived processes to queue
for(int i = 0; i < n; i++)
{
if(at[i] <= time && visited[i] == 0)
{
queue[rear++] = i;
visited[i] = 1;
}
}
// If current process still has remaining time
if(rt[idx] > 0)
{
queue[rear++] = idx;
}
// If queue empty but processes still left
if(front == rear)
{
for(int i = 0; i < n; i++)
{
if(rt[i] > 0)
{
queue[rear++] = i;
visited[i] = 1;
break;
}
}
}
}

// Calculate TAT and WT


for(int i = 0; i < n; i++)
{
tat[i] = ct[i] - at[i];
wt[i] = tat[i] - bt[i];
total_wt += wt[i];
total_tat += tat[i];
}
// Output
printf("\nPID\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]);
}
printf("\nAverage Waiting Time = %.2f", total_wt / n);
printf("\nAverage Turnaround Time = %.2f\n", total_tat / n);
return 0;
}

Output:

Conclusion:
Round Robin scheduling is a preemptive algorithm designed to provide fairness
among processes in a time-sharing system. Each process receives equal CPU
time in cyclic order, preventing starvation. The efficiency of the algorithm
depends on the appropriate selection of the time quantum. With a balanced
time quantum, Round Robin provides good response time and fairness, making
it suitable for interactive systems.

You might also like