Operating Systems: Guru Tegh Bahadur Institute of Technology
Operating Systems: Guru Tegh Bahadur Institute of Technology
TECHNOLOGY
Operating Systems
Practical File
7. Process Management
EXPERIMENT – 1
AIM: C program to implement FCFS scheduling algorithm.
THEORY:
FCFS is the first algorithm of CPU Process Scheduling Algorithm. In First Come First Serve
Algorithm what we do is to allow the process to execute in linear manner.
This means that whichever process enters process enters the ready queue first is executed
first. This shows that First Come First Serve Algorithm follows First In First Out (FIFO)
principle. The First Come First Serve Algorithm can be executed in Pre Emptive and Non Pre
Emptive manner.
1. Implementation is simple.
2. Does not cause any causalities while using
3. It adopts a non pre-emptive and pre-emptive strategy.
4. It runs each procedure in the order that they are received.
5. Arrival time is used as a selection criterion for procedures.
PROGRAM:
1. #include <stdio.h>
2. int main()
3. {
4. int pid[15];
5. int bt[15];
6. int n;
7. printf("Enter the number of processes: ");
8. scanf("%d",&n);
9.
10. printf("Enter process id of all the processes: ");
11. for(int i=0;i<n;i++)
12. {
13. scanf("%d",&pid[i]);
14. }
15.
16. printf("Enter burst time of all the processes: ");
17. for(int i=0;i<n;i++)
18. {
19. scanf("%d",&bt[i]);
20. }
21.
22. int i, wt[n];
23. wt[0]=0;
24.
25. //for calculating waiting time of each process
26. for(i=1; i<n; i++)
27. {
28. wt[i]= bt[i-1]+ wt[i-1];
29. }
30.
31. printf("Process ID Burst Time Waiting Time TurnAround Time\n");
32. float twt=0.0;
33. float tat= 0.0;
34. for(i=0; i<n; i++)
35. {
36. printf("%d\t\t", pid[i]);
37. printf("%d\t\t", bt[i]);
38. printf("%d\t\t", wt[i]);
39.
40. //calculating and printing turnaround time of each process
41. printf("%d\t\t", bt[i]+wt[i]);
42. printf("\n");
43.
44. //for calculating total waiting time
45. twt += wt[i];
46.
47. //for calculating total turnaround time
48. tat += (wt[i]+bt[i]);
49. }
50. float att,awt;
51.
52. //for calculating average waiting time
53. awt = twt/n;
54.
55. //for calculating average turnaround time
56. att = tat/n;
57. printf("Avg. waiting time= %f\n",awt);
58. printf("Avg. turnaround time= %f",att);
59. }
OUTPUT:
(EXP-1 : FCFS Scheduling)
EXPERIMENT – 2
AIM: C program to implement a round robin scheduling algorithm.
THEORY:
Round Robin Scheduling is a CPU scheduling algorithm in which each process is executed
for a fixed time slot. Since the resources are snatched after the time slot, round robin is pre-
emptive.
Pre-emptive: In this type, resources can be voluntarily snatched.
Non-Pre-emptive: In this type, if a process is once started, it will execute completely i.e
resources cannot be snatched.
Waiting Time: Time Difference between turnaround time and burst time.
Waiting Time = Turnaround Time – Burst Time
PROGRAM:
1. #include<stdio.h>
2. #include<conio.h>
3. void main()
4. {
5. // initlialize the variable name
6. int i, NOP, sum=0,count=0, y, quant, wt=0, tat=0, at[10], bt[10], temp[10];
7. float avg_wt, avg_tat;
8. printf(" Total number of process in the system: ");
9. scanf("%d", &NOP);
10. y = NOP; // Assign the number of process to variable y
11.
12. // Use for loop to enter the details of the process like Arrival time and the Burst Time
13. for(i=0; i<NOP; i++)
14. {
15. printf("\n Enter the Arrival and Burst time of the Process[%d]\n", i+1);
16. printf(" Arrival time is: \t"); // Accept arrival time
17. scanf("%d", &at[i]);
18. printf(" \nBurst time is: \t"); // Accept the Burst time
19. scanf("%d", &bt[i]);
20. temp[i] = bt[i]; // store the burst time in temp array
21. }
22. // Accept the Time qunat
23. printf("Enter the Time Quantum for the process: \t");
24. scanf("%d", &quant);
25. // Display the process No, burst time, Turn Around Time and the waiting time
26. printf("\n Process No \t\t Burst Time \t\t TAT \t\t Waiting Time ");
27. for(sum=0, i = 0; y!=0; )
28. {
29. if(temp[i] <= quant && temp[i] > 0) // define the conditions
30. {
31. sum = sum + temp[i];
32. temp[i] = 0;
33. count=1;
34. }
35. else if(temp[i] > 0)
36. {
37. temp[i] = temp[i] - quant;
38. sum = sum + quant;
39. }
40. if(temp[i]==0 && count==1)
41. {
42. y--; //decrement the process no.
43. printf("\nProcess No[%d] \t\t %d\t\t\t\t %d\t\t\t %d", i+1, bt[i], sum-at[i], sum-
at[i]-bt[i]);
44. wt = wt+sum-at[i]-bt[i];
45. tat = tat+sum-at[i];
46. count =0;
47. }
48. if(i==NOP-1)
49. {
50. i=0;
51. }
52. else if(at[i+1]<=sum)
53. {
54. i++;
55. }
56. else
57. {
58. i=0;
59. }
60. }
61. // represents the average waiting time and Turn Around time
62. avg_wt = wt * 1.0/NOP;
63. avg_tat = tat * 1.0/NOP;
64. printf("\n Average Turn Around Time: \t%f", avg_wt);
65. printf("\n Average Waiting Time: \t%f", avg_tat);
66. getch();
67. }
OUTPUT:
(EXP-2 : Round Robin Scheduling)
EXPERIMENT – 3
AIM: Implementation of the following Memory Allocation Methods for fixed partition
a) First Fit b) Worst Fit c) Best Fit.
THEORY:
1. First Fit: In the first fit, the partition is allocated which is the first sufficient block
from the top of Main Memory. It scans memory from the beginning and chooses the
first available block that is large enough. Thus it allocates the first hole that is large
enough.
2. Best Fit Allocate the process to the partition which is the first smallest sufficient
partition among the free available partition. It searches the entire list of holes to find
the smallest hole whose size is greater than or equal to the size of the process.
3. Worst Fit Allocate the process to the partition which is the largest sufficient among
the freely available partitions available in the main memory. It is opposite to the
best-fit algorithm. It searches the entire list of holes to find the largest hole and
allocate it to process.
Program:
// Driver code
int main()
{
int m; //number of blocks in the memory
int n; //number of processes in the input queue
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 426};
m = sizeof(blockSize) / sizeof(blockSize[0]);
n = sizeof(processSize) / sizeof(processSize[0]);
return 0 ;
}
Output:
(EXP-3 : First Fit Memory Allocation)
WORST FIT MEMORY ALLOCATION:
Implementation:
1. Input memory blocks and processes with sizes.
2. Initialize all memory blocks as free.
3. Start by picking each process and find the maximum block size that can be assigned
to current process i.e.,
find max(bockSize[1], blockSize[2],.....blockSize[n]) > processSize[current], if
found then assign it to the current process.
4. If not then leave that process and keep checking
5. the further processes.
Program:
#include <stdio.h>
#include <stdlib.h>
if (wstIdx != -1) {
allocation[i] = wstIdx;
blockSize[wstIdx] -= processSize[i];
}
}
printf("\nProcess No.\tProcess Size\tBlock no.\n");
for (int i = 0; i < n; i++) {
printf(" %d\t\t%d\t\t", i + 1, processSize[i]);
if (allocation[i] != -1)
printf("%d", allocation[i] + 1);
else
printf("Not Allocated");
printf("\n");
}
free(allocation);
}
int main() {
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417};
int m = sizeof(blockSize) / sizeof(blockSize[0]);
int n = sizeof(processSize) / sizeof(processSize[0]);
worstFit(blockSize, m, processSize, n);
return 0;
}
Output:
(EXP-3 : Worst Fit Memory Allocation)
Program:
#include<stdio.h>
int allocation[n];
if (bestIdx != -1) {
allocation[i] = bestIdx;
blockSize[bestIdx] -= processSize[i];
}
}
printf("\nProcess No.\tProcess Size\tBlock no.\n");
for (int i = 0; i < n; i++) {
printf(" %d\t\t%d\t\t", i+1, processSize[i]);
if (allocation[i] != -1)
printf("%d", allocation[i] + 1);
else
printf("Not Allocated");
printf("\n");
}
}
int main() {
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 42};
int m = sizeof(blockSize) / sizeof(blockSize[0]);
int n = sizeof(processSize) / sizeof(processSize[0]);
bestFit(blockSize, m, processSize, n);
return 0;
}
Output:
(EXP-3 : Best Fit Memory Allocation)
EXPERIMENT – 4
AIM: Write a program to implement reader/writer problems using semaphores.
THEORY:
The reader/writer problem is a classic synchronization problem. It deals with concurrent
access to shared resources where multiple processes are involved. The problem can be
defined as follows:
- Multiple readers can simultaneously access a shared resource without any problems.
- Only one writer can access the resource at a time, and no readers can access the resource
while a writer is writing.
Algorithm:
Initialization:
- Initialize the `mutex` semaphore to 1.
- Initialize the `write` semaphore to 1.
- Initialize `read_count` to 0.
Reader Process:
1. Wait on `mutex`.
2. Increment `read_count`.
3. If `read_count` is 1, wait on `write` to prevent writers.
4. Signal `mutex`.
5. Read the data from the shared resource.
6. Wait on `mutex`.
7. Decrement `read_count`.
8. If `read_count` is 0, signal `write` to allow writers.
9. Signal `mutex`.
Writer Process:
1. Wait on `write` to ensure exclusive access for writing.
2. Write data to the shared resource.
3. Signal `write` to release the resource.
PROGRAM
#include <stdio.h>
#include <pthread.h>
int readcount = 0, writecount = 0, sh_var = 5, bsize[5];
pthread_mutex_t x, y, z;
pthread_cond_t rsem, wsem;
void *reader(void *);
void *writer(void *);
void *reader(void *i)
{
printf("\n-------------------------");
printf("\n\n reader-%ld is reading", (long)i);
pthread_mutex_lock(&z);
pthread_mutex_lock(&rsem);
pthread_mutex_lock(&x);
readcount++;
if (readcount == 1)
pthread_mutex_lock(&wsem);
pthread_mutex_unlock(&x);
pthread_mutex_unlock(&rsem);
pthread_mutex_unlock(&z);
printf("\nupdated value: %d", sh_var);
pthread_mutex_lock(&x);
readcount--;
if (readcount == 0)
pthread_mutex_unlock(&wsem);
pthread_mutex_unlock(&x);
}
pthread_exit(NULL);
}
OUTPUT:
(EXP-4 : reader/writer problems using semaphores.)
EXPERIMENT – 5
AIM: Write a program to implement Banker’s algorithm for deadlock avoidance.
THEORY:
The banker’s algorithm is a resource allocation and deadlock avoidance algorithm that tests
for safety by simulating the allocation for the predetermined maximum possible amounts of
all resources, then makes an “s-state” check to test for possible activities, before deciding
whether allocation should be allowed to continue.
Banker’s Algorithm
1. Active:= Running U Blocked;
for k=1…r
New_ request[k]:= Requested_ resources[requesting_ process, k];
2. Simulated_ allocation:= Allocated_ resources;
for k=1…..r //Compute projected allocation state
Simulated_ allocation [requesting _process, k]:= Simulated_ allocation [requesting
_process, k] + New_ request[k];
3. feasible:= true;
for k=1….r // Check whether projected allocation state is feasible
if Total_ resources[k]< Simulated_ total_ alloc [k] then feasible:= false;
4. if feasible= true
then // Check whether projected allocation state is a safe allocation state
while set Active contains a process P1 such that
For all k, Total _resources[k] – Simulated_ total_ alloc[k]>= Max_ need [l ,k]-
Simulated_ allocation[l, k]
Delete Pl from Active;
for k=1…..r
Simulated_ total_ alloc[k]:= Simulated_ total_ alloc[k]- Simulated_ allocation[l, k];
5. If set Active is empty
then // Projected allocation state is a safe allocation state
for k=1….r // Delete the request from pending requests
Requested_ resources[requesting_ process, k]:=0;
for k=1….r // Grant the request
Allocated_ resources[requesting_ process, k]:= Allocated_ resources[requesting_
process, k] + New_ request[k];
Total_ alloc[k]:= Total_ alloc[k] + New_ request[k];
PROGRAM:
// Banker's Algorithm
#include <stdio.h>
int main()
{
// P0, P1, P2, P3, P4 are the Process names here
int n, m, i, j, k;
n = 5; // Number of processes
m = 3; // Number of resources
int alloc[5][3] = { { 0, 1, 0 }, // P0 // Allocation Matrix
{ 2, 0, 0 }, // P1
{ 3, 0, 2 }, // P2
{ 2, 1, 1 }, // P3
{ 0, 0, 2 } }; // P4
int max[5][3] = { { 7, 5, 3 }, // P0 // MAX Matrix
{ 3, 2, 2 }, // P1
{ 9, 0, 2 }, // P2
{ 2, 2, 2 }, // P3
{ 4, 3, 3 } }; // P4
int avail[3] = { 3, 3, 2 }; // Available Resources
int f[n], ans[n], ind = 0;
for (k = 0; k < n; k++) {
f[k] = 0;
}
int need[n][m];
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++)
need[i][j] = max[i][j] - alloc[i][j];
}
int y = 0;
for (k = 0; k < 5; k++) {
for (i = 0; i < n; i++) {
if (f[i] == 0) {
int flag = 0;
for (j = 0; j < m; j++) {
if (need[i][j] > avail[j]){
flag = 1;
break;
}
}
if (flag == 0) {
ans[ind++] = i;
for (y = 0; y < m; y++)
avail[y] += alloc[i][y];
f[i] = 1;
}
}
}
}
int flag = 1;
for(int i=0;i<n;i++)
{
if(f[i]==0)
{
flag=0;
printf("The following system is not safe");
break;
}
}
if(flag==1)
{
printf("Following is the SAFE Sequence\n");
for (i = 0; i < n - 1; i++)
printf(" P%d ->", ans[i]);
printf(" P%d", ans[n - 1]);
}
return (0);
OUTPUT:
(EXP-5 : Banker’s algorithm)
EXPERIMENT – 6
AIM: To study of basic UNIX commands and various UNIX editors such as vi, ed, ex and
EMACS
THEORY:
UNIX is a powerful and widely used operating system known for its command-line interface.
To work effectively in a UNIX environment, it is essential to be familiar with basic UNIX
commands and text editors.
UNIX EDITORS:
1. vi:
- Vi is a terminal-based text editor with different modes (normal, insert, and command
mode).
- To open a file in vi: `$ vi filename`
- In normal mode, to insert text, press `i`. To save and exit, press `Esc`, then `:wq`.
Example: Open a file in vi, add text, save, and exit.
$ vi sample.txt
# Press 'i' to enter insert mode and add text.
This is a vi example.
# Press 'Esc' to exit insert mode.
# Enter ':wq' to save and exit.
2. ed:
- Ed is a line-oriented text editor often used for scripting and automation.
- Example: Create a file using ed.
$ ed newfile.txt
a
This is text added using ed.
.
w
q
3. ex:
- Ex is an extended version of ed with a more user-friendly interface.
- Example: Edit a file using ex.
$ ex existingfile.txt
i
This is new text added using ex.
.
w
q
4. EMACS:
- EMACS is a highly extensible text editor with numerous features.
- To open a file in EMACS: `$ emacs filename`
- For basic editing, type text and save with `Ctrl-X Ctrl-S`. To exit, use `Ctrl-X Ctrl-C`.
EXPERIMENT – 7
THEORY:
Fork():
The `fork()` function creates a new process, known as a child process, which is a copy
of the current process (parent).
The child process starts execution from the point where `fork()` was called.
Both the parent and child processes have their own memory space, CPU registers, and
file descriptors.
execv():
The `execv()` function is used to replace the current process image with a new
program.
It loads and runs a new program by specifying its path and command-line arguments.
The old program's code, data, and stack segments are replaced by the new program.
execlp():
`execlp()` is another function to execute a new program, but it searches for the
program in directories listed in the `PATH` environment variable.
This means you only need to specify the program's name without its full path.
wait():
The `wait()` function is used for process synchronization, specifically to wait for child
processes to terminate.
It allows the parent process to block until a child process exits, at which point it can
collect information about the child's exit status.
sleep():
The `sleep()` function introduces a time delay in the execution of a program.
It pauses the program for a specified number of seconds, allowing other processes to
execute.
OUTPUT:
OUTPUT:
To implement execlp function
PROGRAM:
1. #include <unistd.h>
2. #include <stdio.h>
3.
4. int main() {
5. printf("Executing ls command...\n");
6. execlp("ls", "ls", "-l", NULL);
7. return 0;
8. }
OUTPUT:
PROGRAM:
OUTPUT:
PROGRAM:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
int main()
{
int sleep_seconds = 5;
printf("Calling the sleep function for %d seconds\n", sleep_seconds);
printf("Timestamp: %d\n",(int)time(NULL));
sleep(sleep_seconds);
printf("Timestamp: %d\n",(int)time(NULL));
return 0;
}
OUTPUT:
EXPERIMENT – 8
AIM: To write simple shell programs by using conditional, branching and looping statements
Conditional Statements: There are total 5 conditional statements which can be used in
bash programming
1. if statement
This block will process if specified condition is true.
Syntax:
if [ expression ]
then
statement
fi
2. if-else statement
If specified condition is not true in if part then else part will be execute.
Syntax
if [ expression ]
then
statement1
else
statement2
fi
5. switch statement
Syntax:
case in
Pattern 1) Statement 1;;
Pattern n) Statement n;;
esac
Looping Statements in Shell Scripting: There are total 3 looping statements that can be
used in bash programming
1. while statement
while <condition>
do
<command 1>
…
done
2. for statement
The for loop operates on lists of items. It repeats a set of commands for every item in a list.
for <var> in <value1 value2 ... valuen>
do
<command 1>
…
done
3. until statement
until <condition>
do
<command 1>
…
done
Branching statements:
Branching statements allow the flow of execution to jump to a different part of the program.
The common branching statements used within other control structures
include: break, continue, return, and goto. The goto is rarely used in modular structured
programming. Additionally, we will add to our list of branching items a pre-defined function
commonly used in programming languages of: exit.
PROGRAM:
Program 8.1
Output
Program8.2
Output
Program 8.3
Output:
Program 8.4
#for loop and break
Program8.5
#While loop
Program8.6
#Until
EXPERIMENT – 9
PROGRAM:
OUTPUT: