CSL 204 Operating Systems Lab
CSL 204 Operating Systems Lab
LAB MANUAL
We intend to facilitate our students to assimilate the latest technological know-how and to imbibe discipline,
culture and spiritually, and to mould them in to technological giants, dedicated research scientists and
intellectual leaders of the country who can spread the beams of light and happiness among the poor and the
underprivileged.
DEPARTMENT VISSION
To develop professionally ethical and socially responsible Mechatronics engineers to serve the humanity
through quality professional education.
DEPARTMENT MISSION
1) The department is committed to impart the right blend of knowledge and quality education to create
professionally ethical and socially responsible graduates.
2) The department is committed to impart the awareness to meet the current challenges in technology.
PEO2: Graduates will be able to Analyse, design and development of novel Software Packages,
Web Services, System Tools and Components as per needs and specifications.
PEO3: Graduates will be able to demonstrate their ability to adapt to a rapidly changing environment by
PEO4: Graduates will be able to adopt ethical attitudes, exhibit effective communication skills,
PSO1: Ability to Formulate and Simulate Innovative Ideas to provide software solutions for Real-time
Problems and to investigate for its future scope.
PSO2: Ability to learn and apply various methodologies for facilitating development of high quality
System Software Tools and Efficient Web Design Models with a focus on performance optimization.
PSO3: Ability to inculcate the Knowledge for developing Codes and integrating hardware/software
products in the domains of Big Data Analytics, Web Applications and Mobile Apps to create innovative
career path and for the socially relevant issues.
COURSE OUTCOME
1. Read carefully and understand the description of the experiment in the lab manual. You may
go to the lab at an earlier date to look at the experimental facility and understand it better.
Consult the appropriate references to be completely familiar with the concepts and hardware.
2. Make sure that your observation for previous week experiment is evaluated by the faculty
member and you have transferred all the contents to your record before entering to the
lab/workshop.
3. At the beginning of the class, if the faculty or the instructor finds that a student is not
adequately prepared, they will be marked as absent and not be allowed to perform the
experiment.
4. Bring necessary material needed (writing materials, graphs, calculators, etc.) to perform the
required preliminary analysis. It is a good idea to do sample calculations and as much of the
analysis as possible during the session. Faculty help will be available. Errors in the procedure
may thus be easily detected and rectified.
5. Please actively participate in class and don’t hesitate to ask questions. Please utilize the
teaching assistants fully. To encourage you to be prepared and to read the lab manual before
coming to the laboratory, unannounced questions may be asked at any time during the lab.
6. Carelessness in personal conduct or in handling equipment may result in serious injury to the
individual or the equipment. Do not run near moving machinery/equipment. Always be on the
alert for strange sounds. Guard against entangling clothes in moving parts of machinery.
7. Students must follow the proper dress code inside the laboratory. To protect clothing from
dirt, wear a lab coat. Long hair should be tied back. Shoes covering the whole foot will have to
be worn.
8. In performing the experiments, please proceed carefully to minimize any water spills,
especially on the electric circuits and wire.
9. Maintain silence, order and discipline inside the lab. Don’t use cell phones inside the
laboratory.
10. Any injury no matter how small must be reported to the instructor immediately.
11. Check with faculty members one week before the experiment to make sure that you have the
handout for that experiment and all the apparatus.
3. Make sure you understand what kind of report is to be prepared and due submission of record
is next lab class.
4. Do sample calculations and some preliminary work to verify that the experiment was
successful
Students must participate in all laboratory exercises as scheduled. They must obtain
permission from the faculty member for absence, which would be granted only under justifiable
circumstances. In such an event, a student must make arrangements for a make-up laboratory,
which will be scheduled when the time is available after completing one cycle. Late submission
will be awarded less mark for record and internals and zero in worst cases.
LABORATORY POLICIES
1. Food, beverages & mobile phones are not allowed in the laboratory at any time.
3. Organizing laboratory experiments requires the help of laboratory technicians and staff. Be
punctual.
2. Write programs using the following system calls of Linux operating system:
3. Write programs using the I/O system calls of Linux operating system (open, read, write)
Given the list of processes, their CPU burst times and arrival times, display/print the
Gantt chart for FCFS and SJF. For each of the scheduling policies, compute and print the
8. Write a C program to simulate Bankers algorithm for the purpose of deadlock avoidance.
10. Write a C program to simulate page replacement algorithms a) FIFO b) LRU c) LFU
12. Write a program for file manipulation for display a file and directory in memory.
INDEX
PAGE
EXP NO EXPERIMENT NAME
NO MARKS SIGN
SYSTEM CALLS OF LINUX OPERATING SYSTEM:
1 12
3 SEMAPHORES IMPLEMENTATION 23
TOTAL MARKS:
EXPERIMENT – 1
AIM:
To familiarize with Linux basic commands, directory structure, file and directory operations.
DESCRIPTION
bin
- Here “/” indicates root directory and “~” indicates home directory.
-To move step by step backwards we use:
cd<space>..
(b) ls: - It is used to list all the files in the current directory.
-The hidden files in the directory can be listed using the command:
ls<space>-a
(m) man: -It is used to get the manual of each of the commands.
man<space><command>
Directory structure:
The Unix operating system consists of a single file system. All the controlling directories is present
in the main file system termed as the root directory of the operating system. The different
directories in the root are as follows:
-The initial program to be loaded on to the ram and the kernel is situated in
this directory.
-All the known devices will have a description and the newly installed
devices will have an entry in this directory.
(4) etc: -This is used to store the configuration files of the system.
-User login is directed to this and all home directory files are here.
(8) mnt: -All the mounted drives details will be stored here.
-All the processes are here and process ids are displayed as sub-
directories which contains its resources.
(11) lost+found: -This is an administrative level directory that contains recovery bits
for the deleted files or applications.
(13) sbin: -This also contains system administrative files but can be
accessed by all users.
(15) sys: -This contains system related files like power related files.
(18) var: -This is used to store variable files like system logs.
VIVA QUESTIONS
EXPERIMENT – 2
AIM:
Shared memory is a memory shared between two or more processes. However, why do we need to share
memory or some other means of communication?
To reiterate, each process has its own address space, if any process wants to communicate with some
information from its own address space to other processes, then it is only possible with IPC (inter process
communication) techniques. As we are already aware, communication can be between related or
unrelated processes.
Usually, inter-related process communication is performed using Pipes or Named Pipes. Unrelated
processes (say one process running in one terminal and another process in another terminal)
communication can be performed using Named Pipes or through popular IPC techniques of Shared
Memory and Message Queues.
We have seen the IPC techniques of Pipes and Named pipes and now it is time to know the remaining
IPC techniques viz., Shared Memory, Message Queues, Semaphores, Signals, and Memory Mapping.
We know that to communicate between two or more processes, we use shared memory but before using
the shared memory what needs to be done with the system calls, let us see this −
• Create the shared memory segment or use an already created shared memory segment (shmget())
• Attach the process to the already created shared memory segment (shmat())
• Detach the process from the already attached shared memory segment (shmdt())
• Control operations on the shared memory segment (shmctl())
Let us look at a few details of the system calls related to shared memory.
#include <sys/ipc.h>
#include <sys/shm.h>
The above system call creates or allocates a System V shared memory segment. The arguments that need
to be passed are as follows −
The first argument, key, recognizes the shared memory segment. The key can be either an arbitrary
value or one that can be derived from the library function ftok(). The key can also be IPC_PRIVATE,
means, running processes as server and client (parent and child relationship) i.e., inter-related process
communiation. If the client wants to use shared memory with this key, then it must be a child process of
the server. Also, the child process needs to be created after the parent has obtained a shared memory.
The second argument, size, is the size of the shared memory segment rounded to multiple of
PAGE_SIZE.
The third argument, shmflg, specifies the required shared memory flag/s such as IPC_CREAT (creating
new segment) or IPC_EXCL (Used with IPC_CREAT to create new segment and the call fails, if the
segment already exists). Need to pass the permissions as well.
This call would return a valid shared memory identifier (used for further calls of shared memory) on
success and -1 in case of failure. To know the cause of failure, check with errno variable or perror()
function.
#include <sys/types.h>
#include <sys/shm.h>
The above system call performs shared memory operation for System V shared memory segment i.e.,
attaching a shared memory segment to the address space of the calling process. The arguments that need
to be passed are as follows −
The first argument, shmid, is the identifier of the shared memory segment. This id is the shared memory
identifier, which is the return value of shmget() system call.
The second argument, shmaddr, is to specify the attaching address. If shmaddr is NULL, the system
by default chooses the suitable address to attach the segment. If shmaddr is not NULL and SHM_RND
is specified in shmflg, the attach is equal to the address of the nearest multiple of SHMLBA (Lower
Boundary Address). Otherwise, shmaddr must be a page aligned address at which the shared memory
attachment occurs/starts.
The third argument, shmflg, specifies the required shared memory flag/s such as SHM_RND (rounding
off address to SHMLBA) or SHM_EXEC (allows the contents of segment to be executed) or
SHM_RDONLY (attaches the segment for read-only purpose, by default it is read-write) or
SHM_REMAP (replaces the existing mapping in the range specified by shmaddr and continuing till the
end of segment).
This call would return the address of attached shared memory segment on success and -1 in case of
failure. To know the cause of failure, check with errno variable or perror() function.
#include <sys/types.h>
#include <sys/shm.h>
The above system call performs shared memory operation for System V shared memory segment of
detaching the shared memory segment from the address space of the calling process. The argument that
needs to be passed is −
The argument, shmaddr, is the address of shared memory segment to be detached. The to-be-detached
segment must be the address returned by the shmat() system call.
This call would return 0 on success and -1 in case of failure. To know the cause of failure, check with
errno variable or perror() function.
#include <sys/ipc.h>
#include <sys/shm.h>
The above system call performs control operation for a System V shared memory segment. The following
arguments needs to be passed −
The first argument, shmid, is the identifier of the shared memory segment. This id is the shared memory
identifier, which is the return value of shmget() system call.
The second argument, cmd, is the command to perform the required control operation on the shared
memory segment.
• IPC_STAT − Copies the information of the current values of each member of struct shmid_ds to
the passed structure pointed by buf. This command requires read permission to the shared
memory segment.
• IPC_SET − Sets the user ID, group ID of the owner, permissions, etc. pointed to by structure
buf.
• IPC_RMID − Marks the segment to be destroyed. The segment is destroyed only after the last
process has detached it.
• IPC_INFO − Returns the information about the shared memory limits and parameters in the
structure pointed by buf.
• SHM_INFO − Returns a shm_info structure containing information about the consumed system
resources by the shared memory.
The third argument, buf, is a pointer to the shared memory structure named struct shmid_ds. The values
of this structure would be used for either set or get as per cmd.
This call returns the value depending upon the passed command. Upon success of IPC_INFO and
SHM_INFO or SHM_STAT returns the index or identifier of the shared memory segment or 0 for other
operations and -1 in case of failure. To know the cause of failure, check with errno variable or perror()
function.
• Create two processes, one is for writing into the shared memory (shm_write.c) and another is for
reading from the shared memory (shm_read.c)
• The program performs writing into the shared memory by write process (shm_write.c) and
reading from the shared memory by reading process (shm_read.c)
• In the shared memory, the writing process, creates a shared memory of size 1K (and flags) and
attaches the shared memory
• The write process writes 5 times the Alphabets from ‘A’ to ‘E’ each of 1023 bytes into the shared
memory. Last byte signifies the end of buffer
• Read process would read from the shared memory and write to the standard output
• Reading and writing process actions are performed simultaneously
• After completion of writing, the write process updates to indicate completion of writing into the
shared memory (with complete variable in struct shmseg)
• Reading process performs reading from the shared memory and displays on the output until it
gets indication of write process completion (complete variable in struct shmseg)
• Performs reading and writing process for a few times for simplication and also in order to avoid
infinite loops and complicating the program
PROGRAM :
//Write program
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main()
{
// ftok to generate unique key
key_t key = ftok("shmfile",65);
// shmget returns an identifier in shmid
//Read program
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main()
{
// ftok to generate unique key
key_t key = ftok("shmfile",65);
// shmget returns an identifier in shmid
int shmid = shmget(key,1024,0666|IPC_CREAT);
// shmat to attach to shared memory
char *str = (char*) shmat(shmid,(void*)0,0);
printf("Data read from memory: %s\n",str);
//detach from shared memory
shmdt(str);
// destroy the shared memory
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
Output:
VIVA QUESTIONS
EXPERIMENT – 3
SEMAPHORES IMPLEMENTATION
AIM:
Write a C program to implement the Producer consumer problem using semaphores
Semaphore is a simply a variable. This variable is used to solve critical section problem and to
achieve process synchronization in the multi-processing environment.
The two most common kinds of semaphores are counting semaphores and binary semaphores.
Semaphores are of two types:
1. Binary Semaphore – This is also known as mutex lock. It can have only two values – 0 and
1. Its value is initialized to 1. It is used to implement solution of critical section problem
with multiple processes.
2. Counting Semaphore – Its value can range over an unrestricted domain. It is used
to control access to a resource that has multiple instances.
P and V are the two operations which can be used to access and change the value of semaphore
variable
1. P operation is also called wait, sleep or down operation and V operation is also called
signal, wake-up or up operation.
2. Both operations are atomic and semaphore(s) is always initialized to one.
3. The wait() operation reduces the value of semaphore by 1 and the signal()
operation increases its value by 1.
4. A critical section is surrounded by both operations to implement process
synchronization. See below image. Critical section of Process P is in between P and V
operation.
PROGRAM:
#include<stdio.h>
void main()
{
int buffer[10],bufsize = 5, in, out, pro, cons,
choice; in=out=0;
do{
e); switch(choice){
}while(choice!=3);
}
OUTPUT
VIVA QUESTIONS
1. What is semaphore
2. What are the types of semaphores
3. What is producer consumer problem
EXPERIMENT – 4
AIM
The process with the minimal arrival time will get the CPU first.
The lesser the arrival time, the sooner will the process gets the CPU.
The Turnaround time and the waiting time are calculated by using the following formula.
Time
0 0 2 2 2 0
1 1 6 8 7 1
2 2 4 12 8 4
3 3 9 21 18 9
4 4 12 33 29 17
Shortest-Job-First Scheduling
This algorithm associates with each process the length of the process’s next CPU burst. When the
CPU is available, it is assigned to the process that has the smallest next CPU burst. If the next CPU
bursts of two processes are the same, FCFS scheduling is used to break the tie. Note that a more
appropriate term for this scheduling method would be the shortest-next- CPU-burst algorithm,
because scheduling depends on the length of the next CPU burst of a process, rather than its total
length.We use the term SJF because most people and textbooks use this term to refer to this type of
scheduling. As an example of SJF scheduling, consider the following set of processes, with the
length of the CPU burst given in milliseconds:
The waiting time is 3 milliseconds for process P1, 16 milliseconds for process P2, 9 milliseconds
for process P3, and 0 milliseconds for process P4. Thus, the average waiting time is (3 + 16 + 9 +
0)/4 = 7 milliseconds. By comparison, if we were using the FCFS scheduling scheme, the average
waiting time would be 10.25 milliseconds.
Priority Scheduling
The SJF algorithm is a special case of the general priority-scheduling algorithm. Apriority is
associated with each process, and the CPUis allocated to the process with the highest priority. Equal-
priority processes are scheduled in FCFS order. An SJF algorithm is simply a priority algorithm
where thepriority (p) is the inverse of the (predicted) next CPU burst. The larger the CPU burst, the
lower the priority, and vice versa. Note that we discuss scheduling in terms of high priority and low
priority.
Priorities are generally indicated by some fixed range of numbers, such as 0 to 7 or 0 to 4,095.
However, there is no general agreement on whether 0 is the highest or lowest priority. Some systems
use low numbers to represent low priority; others use low numbers for high priority. This difference
can lead to confusion. In this text, we assume that low numbers represent high priority. As an
example, consider the following set of processes, assumed to have arrived at time 0 in the order P1,
P2, · · ·, P5, with the length of the CPU burst given in milliseconds:
Round-Robin Scheduling
The round-robin (RR) scheduling algorithm is designed especially for timesharing systems. It is
similar to FCFS scheduling, but preemption is added to enable the system to switch between
processes. A small unit of time, called a time quantum or time slice, is defined. A time quantum is
generally from 10 to 100 milliseconds in length. The ready queue is treated as a circular queue. The
CPU scheduler goes around the ready queue, allocating the CPU to each process for a time interval
of up to 1 time quantum.
To implement RR scheduling, we again treat the ready queue as a FIFO queue of processes. New
processes are added to the tail of the ready queue. The CPU scheduler picks the first process from
the ready queue, sets a timer to interrupt after 1 time quantum, and dispatches the process. One of
two things will then happen. The process may have a CPU burst of less than 1 time quantum. In this
case, the process itself will release the CPU voluntarily. The scheduler will then proceed to the next
process in the ready queue. If the CPU burst of the currently running process is longer than 1 time
quantum, the timer will go off and will cause an interrupt to the operating system. A context switch
will be executed, and the process will be put at the tail of the ready queue. The CPU scheduler will
then select the next process in the ready queue.
The average waiting time under the RR policy is often long. Consider the following set of processes
that arrive at time 0, with the length of the CPU burst given in milliseconds:
Let’s calculate the average waiting time for this schedule. P1 waits for 6 milliseconds (10 - 4), P2
waits for 4 milliseconds, and P3 waits for 7 milliseconds. Thus, the average waiting time is 17/3 =
5.66
PROGRAM
#include<stdio.h>
void main()
int i=0,j=0,b[i],g[20],p[20],w[20],t[20],a[20],n=0,m;
float avgw=0,avgt=0;
scanf("%d",&n);
for(i=0;i<n;i++)
printf("Process ID : ");
scanf("%d",&p[i]);
scanf("%d",&b[i]);
scanf("%d",&a[i]);
int temp=0;
for(i=0;i<n-1;i++)
for(j=0;j<n-1;j++)
if(a[j]>a[j+1])
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
temp=b[j];
b[j]=b[j+1];
b[j+1]=temp;
temp=p[j];
p[j]=p[j+1];
p[j+1]=temp;
g[0]=0;
for(i=0;i<=n;i++)
g[i+1]=g[i]+b[i];
for(i=0;i<n;i++)
t[i]=g[i+1]-a[i];
w[i]=t[i]-b[i];
avgw+=w[i];
avgt+=t[i];
avgw=avgw/n;
avgt=avgt/n;
printf("pid\tarrivalT\tBrustT\tCompletionT\tWaitingtime\tTurnaroundTi\n");
for(i=0;i<n;i++)
printf("%d\t%d\t%d\t%d\t\t%d\t\t\t%d\n",p[i],a[i],b[i],g[i+1],w[i],t[i]);
Output
1 0 4 4 0 4
2 1 3 7 3 6
3 2 1 8 5 6
4 3 2 10 5 7
5 4 5 15 6 11
#include<stdio.h>
void main()
{
int i=0,j=0,p[i],b[i],g[20],w[20],t[20],a[20],n=0,m;
int k=1,min=0,btime=0;
float avgw=0,avgt=0;
printf("Enter the number of process : ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\nProcess id : ");
scanf("%d",&p[i]);
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
temp=b[j];
b[j]=b[j+1];
b[j+1]=temp;
temp=p[j];
p[j]=p[j+1];
p[j+1]=temp;
}
}
}
for(i=0;i<n;i++)
{
btime=btime+b[i];
min=b[k];
for(j=k;j<n;j++)
{
if(btime >= a[j] && b[j]<min)
{
temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
temp=b[j];
b[j]=b[j-1];
b[j-1]=temp;
temp=p[j]
}
} k++;
g[0]=a[0];
for(i=0;i<n;i++)
{
g[i+1]=g[i]+b[i];
if(g[i]<a[i])
g[i]=a[i];
}
for(i=0;i<n;i++)
{
t[i]=g[i+1]-a[i];
w[i]=t[i]-b[i];
avgw+=w[i];
avgt+=t[i];
}
avgw=avgw/n;
avgt=avgt/n;
printf("pid\tBrustTime\tGantChart\tWaiting time\t\tTurnarround Time\n");
for(i=0;i<n;i++)
{
printf(" %d\t %d\t\t%d-%d\t\t%d\t\t\t%d\n",p[i],b[i],g[i],g[i+1],w[i],t[i]);
}
printf("\nAverage waiting time %f",avgw);
printf("\nAverage turnarround time %f\n",avgt);
OUTPUT
Process id : 1
Burst Time : 7
Arrival Time: 0
Process id : 2
Burst Time : 5
Arrival Time: 1
Process id : 3 Burst
Time : 1 Arrival
Time: 2
Process id : 4 Burst
Time : 2 Arrival
Time: 3
Process id : 5 Burst
Time : 8 Arrival
Time:
3.PRIORITY SCHEDULING
#include<stdio.h>
int main()
{
int burst_time[20], process[20], waiting_time[20], turnaround_time[20], priority[20];
int i, j, limit, sum = 0, position, temp;
float average_wait_time, average_turnaround_time;
printf("Enter Total Number of Processes:\t");
scanf("%d", &limit);
printf("\nEnter Burst Time and Priority For %d Processes\n", limit);
for(i = 0; i < limit; i++)
{
printf("\nProcess[%d]\n", i + 1);
printf("Process Burst Time:\t");
scanf("%d", &burst_time[i]);
printf("Process Priority:\t");
scanf("%d", &priority[i]);
process[i] = i + 1;
}
for(i = 0; i < limit; i++)
{
position = i;
for(j = i + 1; j < limit; j++)
{
if(priority[j] < priority[position])
{
position = j;
}
}
temp = priority[i];
priority[i] = priority[position];
priority[position] = temp;
temp = burst_time[i];
burst_time[i] = burst_time[position];
burst_time[position] = temp;
temp = process[i];
process[i] = process[position];
process[position] = temp;
}
waiting_time[0] = 0;
for(i = 1; i < limit; i++)
{
waiting_time[i] = 0;
for(j = 0; j < i; j++)
{
waiting_time[i] = waiting_time[i] + burst_time[j];
}
sum = sum + waiting_time[i];
}
average_wait_time = sum / limit;
sum = 0;
printf("\nProcess ID\t\tBurst Time\t Waiting Time\t Turnaround Time\n");
for(i = 0; i < limit; i++)
{
turnaround_time[i] = burst_time[i] + waiting_time[i];
sum = sum + turnaround_time[i];
printf("\nProcess[%d]\t\t%d\t\t %d\t\t %d\n", process[i], burst_time[i], waiting_time[i],
turnaround_time[i]);
}
average_turnaround_time = sum / limit;
printf("\nAverage Waiting Time:\t%f", average_wait_time);
printf("\nAverage Turnaround Time:\t%f\n", average_turnaround_time);
return 0;}
OUTPUT
Process id : 1
Burst Time : 15
Priority: 3
Process id : 2
Burst Time : 10
Priority: 2
Process id : 3 Burst
Time : 90
Priority: 1
#include<stdio.h>
int main()
{
int i, limit, total = 0, x, counter = 0, time_quantum;
int wait_time = 0, turnaround_time = 0, arrival_time[10], burst_time[10], temp[10];
float average_wait_time, average_turnaround_time;
printf("\nEnter Total Number of Processes:\t");
scanf("%d", &limit);
x = limit;
for(i = 0; i < limit; i++)
{
printf("\nEnter Details of Process[%d]\n", i + 1);
printf("Arrival Time:\t");
scanf("%d", &arrival_time[i]);
printf("Burst Time:\t");
scanf("%d", &burst_time[i]);
temp[i] = burst_time[i];
}
printf("\nEnter Time Quantum:\t");
scanf("%d", &time_quantum);
printf("\nProcess ID\t\tBurst Time\t Turnaround Time\t Waiting Time\n");
for(total = 0, i = 0; x != 0;)
{
if(temp[i] <= time_quantum && temp[i] > 0)
{
total = total + temp[i];
temp[i] = 0;
counter = 1;
}
else if(temp[i] > 0)
{
temp[i] = temp[i] - time_quantum;
total = total + time_quantum;
}
if(temp[i] == 0 && counter == 1)
{
x--;
printf("\nProcess[%d]\t\t%d\t\t %d\t\t\t %d", i + 1, burst_time[i], total - arrival_time[i],
total - arrival_time[i] - burst_time[i]);
wait_time = wait_time + total - arrival_time[i] - burst_time[i];
turnaround_time = turnaround_time + total - arrival_time[i];
counter = 0;
}
if(i == limit - 1)
{
i = 0;
}
else if(arrival_time[i + 1] <= total)
{
i++;
}
else
{
i = 0;
}
}
average_wait_time = wait_time * 1.0 / limit;
average_turnaround_time = turnaround_time * 1.0 / limit;
printf("\n\nAverage Waiting Time:\t%f", average_wait_time);
printf("\nAvg Turnaround Time:\t%f\n", average_turnaround_time);
return 0;
}
OUTPUT
Process id : 2
Burst Time : 3
Arrival Time:2
Process id : 3 Burst
Time : 2 Arrival
Time:3
VIVA QUESTIONS
1. What are all the scheduling algorithms?
2. What is CPU Scheduler?
3. What is CPU utilization?
4. What is Throughput?
5. Explain Priority Scheduling algorithm?
6. Explain Round Robin?
7. Explain FCFS(First Come First Served)?
EXPERIMENT – 5
AIM:
a) First Fit
b) Worst Fit
c) Best Fit
First Fit
In the first fit approach is to allocate the first free partition or hole large enough which can accommodate
the process. It finishes after finding the first suitable free partition.
Best Fit
The best fit deals with allocating the smallest free partition which meets the requirement of the requesting
process. This algorithm first searches the entire list of free partitions and considers the smallest hole that is
adequate. It then tries to find a hole which is close to actual process size needed.
Worst fit
In worst fit approach is to locate largest available free portion so that the portion left will be big enough to
be useful. It is the reverse of best fit.
PROGRAM
1. FIRST FIT
#include<stdio.h>
struct process
{
int ps;
int flag;
} p[50];
struct sizes
{
int size;
int alloc;
}
s[5];
int main()
{
int i=0,np=0,n=0,j=0;
printf("\n first fit");
printf("\n");
printf("enter the number of blocks \t");
scanf("%d",&n);
printf("\t\t\n enter the size for %d blocks\n",n);
for(i=0;i<n;i++)
{
printf("enter the size for %d block \t",i);
scanf("%d",&s[i].size);
}
printf("\n\t\t enter the number of process\t",i);
scanf("%d",&np);
printf("\n enter the size of %d processors !\t",np);
printf("/n");
for(i=0;i<np;i++)
{
printf("enter the size of process %d\t",i);
scanf("\n%d",&p[i].ps);
}
printf("\n\t\t Allocation of blocks using first fit is as follows\n");
printf("\n\t\t process \t process size\t blocks\n");
for(i=0;i<np;i++)
{
for(j=0;j<n;j++)
{
if(p[i].flag!=1)
{
if(p[i].flag!=1)
{
if(p[i].ps<=s[j].size)
{
if(!s[j].alloc)
{
p[i].flag=1;
s[j].alloc=1;
printf("\n\t\t %d\t\t\t%d\t%d\t",i,p[i].ps,s[j].size);
}
}
}
}
}
}
for(i=0;i<np;i++)
{
if(p[i].flag!=1)
printf("sorry !!!!!!!process %d must wait as there is no sufficient memory");
}
}
OUTPUT
First fit
1 40 100
2 200 250
3 300 300
2. WORST FIT
#include<stdio.h>
int main()
scanf("%d",&number_of_blocks);
scanf("%d",&number_of_files);
scanf("%d", &blocks[m]);
scanf("%d", &files[m]);
if(block_arr[n] != 1)
if(temp >= 0)
file_arr[m] = n;
top = temp;
fragments[m] = top;
block_arr[file_arr[m]] = 1;
top = 0;
fragments[m]);
printf("\n");
return 0;
OUTPUT
Block No.[1] : 50
Block No.[2] : 75
File No.[1] : 20
File No.[3] : 40
0 20 3 300 280
1 100 0 50 0
2 40 0 50 10
3.BEST FIT
#include<stdio.h>
#define MAX 20
int main()
{
int bsize[MAX],fsize[MAX],nb,nf;
int temp,low=10000;
static int bflag[MAX],fflag[MAX];
int i,j;
printf("\n enter the number of blocks");
scanf("%d",&nb);
for(i=1;i<=nb;i++)
{
printf("Enter the size of memory block % d",i);
scanf("%d", &bsize[i]);
}
printf("\n enter the number of files");
scanf("%d",&nf);
for(i=1;i<=nf;i++)
{
printf("\n enetr the size of file %d",i);
scanf("%d",&fsize[i]);
}
for(i=1;i<=nf;i++)
{
for(j=1;j<=nb;j++)
{
if(bflag[j]!=1)
{
temp=bsize[j]-fsize[i];
if(temp>=0)
{
if(low>temp)
{
fflag[i]=j;
low=temp;
}
}
}}
bflag[fflag[i]]=1;
low=10000;
}
printf("\n file no \t file.size\t block no \t block size");
for(i=1;i<=nf;i++)
printf("\n \n %d \t\t%d\t\t%d\t\t%d",i,fsize[i],fflag[i],bsize[fflag[i]]);
}
OUTPUT
1 50 4 50
2 20 1 40
23 225 3 250
VIVA QUESTIONS
EXPERIMENT – 6
AIM:
Initially all slots are empty, so when 1, 3, 0 came they are allocated to the empty slots —> 3 Page Faults.
when 3 comes, it is already in memory so —> 0 Page Faults.
Then 5 comes, it is not available in memory so it replaces the oldest page slot i.e 1. —>1 Page Fault.
6 comes, it is also not available in memory so it replaces the oldest page slot i.e 3 —>1 Page Fault.
Finally when 3 come it is not available so it replaces 0 1 page fault
Initially all slots are empty, so when 7 0 1 2 are allocated to the empty slots —> 4 Page faults
0 is already their so —> 0 Page fault.
when 3 came it will take the place of 7 because it is least recently used —>1 Page fault
0 is already in memory so —> 0 Page fault.
4 will takes place of 1 —> 1 Page Fault
Now for the further page reference string —> 0 Page fault because they are already available in the
memory.
PROGRAM
#include<stdio.h>
int main()
{
int i,j,n,a[50],frame[10],no,k,avail,count=0;
printf("\n enter the number of pages:\n");
scanf("%d",&n);
printf("\n enter the page number:\n");
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
printf("\n enter the number of frames:\n"); scanf("%d",&no);
for(i=0;i<no;i++) frame[i]=-1;
j=0;
printf("ref string\t page frames\n");
for(i=1;i<=n;i++)
{
printf("%d\t\t",a[i]);
avail=0;
for(k=0;k<no;k++)
if(frame[k]==a[i]) avail=1;
if(avail==0)
{
frame[j]=a[i];
j=(j+1)%no;
count++;
for(k=0;k<no;k++)
printf("%d\t",frame[k]);
}
printf("\n");
}
printf("page fault is %d",count); getch();
return 0;
}
OUTPUT
7 0 1 2 0 3 0 4 2 3 0 3 2 1
0 1 7 0 1
7 -1 -1
7 0 -1
7 0 1
2 0 1
2 3 1
2 3 0
2 0 3
4 3 0
4 2 0
4 2 3
0 2 3
0 1 3
0 1 2
7 1 2
7 0 2
7 0 1
#include<stdio.h>
int findLRU(int time[], int n){
int i, minimum = time[0], pos = 0;
int main()
{
int no_of_frames, no_of_pages, frames[10], pages[30], counter = 0, time[10], flag1, flag2, i, j, pos,
faults = 0;
printf("Enter number of frames: ");
scanf("%d", &no_of_frames);
printf("Enter number of pages: ");
scanf("%d", &no_of_pages);
printf("Enter reference string: ");
for(i = 0; i < no_of_pages; ++i){
scanf("%d", &pages[i]);
}
if(frames[j] == pages[i]){
counter++;
time[j] = counter;
flag1 = flag2 = 1;
break;
}
}
if(flag1 == 0){
for(j = 0; j < no_of_frames; ++j){
if(frames[j] == -1){
counter++;
faults++;
frames[j] = pages[i];
time[j] = counter;
flag2 = 1;
break;
}
}
}
if(flag2 == 0){
pos = findLRU(time, no_of_frames);
counter++;
faults++;
frames[pos] = pages[i];
time[pos] = counter;
}
printf("\n");
return 0;
}
OUTPUT
7 0 1 2 0 3 0 4 2 3 0 3 2 1
0 1 7 0 1
7 -1 -1
7 0 -1
7 0 1
2 0 1
2 0 1
2 0 3
2 0 3
4 0 3
4 0 2
4 3 3
0 3 2
0 3 2
0 3 2
1 3 2
1 3 2
1 0 2
1 0 2
1 0 7
1 0 7
1 0 7
#include<stdio.h>
int main()
{
int no_of_frames, no_of_pages, frames[10], pages[30], temp[10], flag1, flag2, flag3, i, j, k, pos,
max, faults = 0;
printf("Enter number of frames: ");
scanf("%d", &no_of_frames);
if(flag1 == 0){
for(j = 0; j < no_of_frames; ++j){
if(frames[j] == -1){
faults++;
frames[j] = pages[i];
flag2 = 1;
break;
}
}
}
if(flag2 == 0){
flag3 =0;
if(flag3 ==0){
max = temp[0];
pos = 0;
printf("\n");
return 0;
}
OUTPUT
7 0 1 2 0 3 0 4 2 3 0 3 2 1
0 1 7 0 1
7 -1 -1
7 0 -1
7 0 1
2 0 1
2 0 1
2 0 3
2 4 3
2 4 3
2 4 3
2 0 3
2 0 3
2 0 3
2 0 1
2 0 1
2 0 1
2 0 1
7 0 1
7 0 1
7 0 1
VIVA QUESTIONS
EXPERIMENT – 7
AIM:
The Banker algorithm, sometimes referred to as the detection algorithm, is a resource allocation and
deadlock avoidance algorithm developed by Edsger Dijkstra that tests for safety by simulating the
allocation of predetermined maximum possible amounts of all resources, and then makes an "s-state"
check to test for possible deadlock conditions for all other pending activities, before deciding whether
allocation should be allowed to continue.
Banker's Algorithm:
Let n be the number of processes in the system and m be the number of resource types. Then we need
the following data structures:
1. Available: A vector of length m indicates the number of available resources of each
type. If Available[j] = k, there are k instances of resource type Rj available.
2. Max: An n×m matrix defines the maximum demand of each process.
If Max[i,j] = k, then Pi may request at most k instances of resource type Rj.
3. Allocation: An n×m matrix defines the number of resources of each type currently
allocated to each process. If Allocation[i,j] = k, then process Pi is currently allocated k
instances of resource type Rj.
4. Need: An n×m matrix indicates the remaining resource need of each process.
If Need[i,j] = k, then Pi may need k more instances of resource type Rj
to complete the task.
PROGRAM
#include<stdio.h>
struct pro{
int all[10],max[10],need[10];
int flag;
};
int i,j,pno,r,nr,id,k=0,safe=0,exec,count=0,wait=0,max_err=0;
struct pro p[10];
int aval[10],seq[10];
void safeState()
{
while(count!=pno){
safe = 0;
for(i=0;i<pno;i++){
if(p[i].flag){
exec = r;
for(j=0;j<r;j++)
{
if(p[i].need[j]>aval[j]){
exec =0;
}
}
if(exec == r){
for(j=0;j<r;j++){
aval[j]+=p[i].all[j];
}
p[i].flag = 0;
seq[k++] = i;
safe = 1;
count++;
}
}
}
if(!safe)
{
printf("System is in Unsafe State\n");
break;
}
}
if(safe){
max_err = 1;
}
if(!max_err && !wait)
safeState();
else if(max_err){
printf("\nProcess has exceeded its maximum usage \n");
}
else{
printf("\nProcess need to wait\n");
}
}
void main()
{
printf("Enter no of process ");
scanf("%d",&pno);
printf("Enter no. of resourses ");
scanf("%d",&r);
printf("Enter Available Resourse of each type ");
for(i=0;i<r;i++){
scanf("%d",&aval[i]);
}
printf("\n\n---Resourse Details---");
for(i=0;i<pno;i++){
printf("\nResourses for process %d\n",i);
printf("\nAllocation Matrix\n");
for(j=0;j<r;j++){
scanf("%d",&p[i].all[j]);
}
printf("Maximum Resourse Request \n");
for(j=0;j<r;j++){
scanf("%d",&p[i].max[j]);
}
p[i].flag = 1;
}
// Calcualting need
for(i=0;i<pno;i++){
for(j=0;j<r;j++){
p[i].need[j] = p[i].max[j] - p[i].all[j];
}
}
//Print Current Details
printf("\nProcess Details\n");
printf("Pid\t\tAllocattion\t\tMax\t\tNeed\n");
for(i=0;i<pno;i++)
{
printf("%d\t\t",i);
for(j=0;j<r;j++){
printf("%d ",p[i].all[j]);
}
printf("\t\t");
for(j=0;j<r;j++){
printf("%d ",p[i].max[j]);
}
printf("\t\t");
for(j=0;j<r;j++){
printf("%d ",p[i].need[j]);
}
printf("\n");
}
//Determine Current State in Safe State
safeState();
int ch=1;
do{
OUTPUT
Enter no of process 5
Enter no. of resourses 3
Enter Available Resourse of each type 3
3
2
---Resourse Details---
Resourses for process 0
Allocation Matrix
010
Maximum Resourse Request
753
Allocation Matrix
302
Maximum Resourse Request
322
Allocation Matrix
302
Maximum Resourse Request
902
Allocation Matrix
211
Maximum Resourse Request
222
Allocation Matrix 0
02
Maximum Resource Request
433
Process Details
Pid Allocation Max Need
0 0 10 7 53 7 4 3
1 3 02 3 22 0 2 0
2 3 02 9 02 6 0 0
3 2 11 2 22 0 1 1
4 0 02 4 33 4 3 1
System is in safe state
VIVA QUESTIONS
1. What is deadlock
2. What is deadlock avoidance
3. What is the purpose of banker’s algorithm
EXPERIMENT – 8
AIM
It is the simplest form of disk scheduling algorithms. The I/O requests are served or processes according
to their arrival. The request arrives first will be accessed and served first. Since it follows the order of
arrival, it causes the wild swings from the innermost to the outermost tracks of the disk and vice versa.
The farther the location of the request being serviced by the read/write head from its current location, the
higher the seek time will be.
Example:
Given the following track requests in the disk queue, compute for the Total Head Movement2 (THM) of
the read/write head: 95, 180, 34, 119, 11, 123, 62, and 64.
Consider that the read/write head is positioned at location 50. Prior to this track location 199 was
serviced. Show the total head movement for a 200 track disk (0-199).
Solution:
Total Head Movement Computation:
(THM) = (180-50) + (180-34) + (119-34) + (119-11) + (123-11) + (123-62) + (64-62)
= 130 + 146 + 85 + 108 + 112 + 61 + 2 (THM) = 644 tracks
Assuming a seek rate of 5 milliseconds is given, we compute for the seek time using the formula: Seek
Time = THM * Seek rate = 644 * 5 ms
Seek Time = 3,220ms
There are some requests that are far from the current location of the R/W head which causes theaccess
arm to travel from innermost to the outermost tracks of the disk or vice versa.In this example, it had a
total of 644 tracks and a seek time of 3,220 milliseconds. Based on the result, this algorithm produced
higher seek rate since it follows the arrival of the track requests.
The computation of the seek time excluded the alpha value because it is not an actual seek or search of a
disk request but a reset of the access arm to the starting position.
PROGRAM
#include<conio.h>
#include<stdio.h>
int main()
{
int i,j,sum=0,n;
int ar[20],tm[20];
int disk;
printf("enter number of location\t");
scanf("%d",&n);
printf("enter position of head\t");
scanf("%d",&disk);
printf("enter elements of disk queue\n");
for(i=0;i<n;i++)
{
scanf("%d",&ar[i]);
tm[i]=disk-ar[i];
if(tm[i]<0)
{
tm[i]=ar[i]-disk;
}
disk=ar[i];
sum=sum+tm[i];
}
/*for(i=0;i<n;i++)
{
printf("\n%d",tm[i]);
} */
printf("\nmovement of total cylinders %d",sum);
getch();
return 0;
}
OUTPUT
2. SCAN Scheduling
#include<stdio.h>
#include<stdlib.h>
int main()
int RQ[100],i,j,n,TotalHeadMoment=0,initial,size,move;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&RQ[i]);
scanf("%d",&initial);
scanf("%d",&size);
printf("Enter the head movement direction for high 1 and for low 0\n");
scanf("%d",&move);
for(i=0;i<n;i++)
for(j=0;j<n-i-1;j++)
if(RQ[j]>RQ[j+1])
int temp;
temp=RQ[j];
RQ[j]=RQ[j+1];
RQ[j+1]=temp;
int index;
for(i=0;i<n;i++)
if(initial<RQ[i])
index=i;
break;
if(move==1)
for(i=index;i<n;i++)
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
TotalHeadMoment=TotalHeadMoment+abs(size-RQ[i-1]-1);
initial = size-1;
for(i=index-1;i>=0;i--)
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
else
for(i=index-1;i>=0;i--)
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
TotalHeadMoment=TotalHeadMoment+abs(RQ[i+1]-0);
initial =0;
for(i=index;i<n;i++)
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
return 0;
OUTPUT
#include<stdio.h>
#include<stdlib.h>
int main()
int RQ[100],i,j,n,TotalHeadMoment=0,initial,size,move;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&RQ[i]);
scanf("%d",&initial);
scanf("%d",&size);
printf("Enter the head movement direction for high 1 and for low 0\n");
scanf("%d",&move);
for(i=0;i<n;i++)
for( j=0;j<n-i-1;j++)
if(RQ[j]>RQ[j+1])
int temp;
temp=RQ[j];
RQ[j]=RQ[j+1];
RQ[j+1]=temp;
int index;
for(i=0;i<n;i++)
if(initial<RQ[i])
index=i;
break;
if(move==1)
for(i=index;i<n;i++)
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
TotalHeadMoment=TotalHeadMoment+abs(size-RQ[i-1]-1);
TotalHeadMoment=TotalHeadMoment+abs(size-1-0);
initial=0;
for( i=0;i<index;i++)
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
else
for(i=index-1;i>=0;i--)
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
TotalHeadMoment=TotalHeadMoment+abs(RQ[i+1]-0);
TotalHeadMoment=TotalHeadMoment+abs(size-1-0);
initial =size-1;
for(i=n-1;i>=index;i--)
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
return 0;
OUTPUT
VIVA QUESTIONS