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

OS Lab Manual-1

The document outlines practical exercises for an Operating System Lab at Vidya College of Engineering, covering various algorithms and system calls. It includes implementations of sorting algorithms, CPU scheduling techniques, inter-process communication problems, and UNIX system calls for process and file management. Each practical is accompanied by example programs and descriptions of the algorithms used.

Uploaded by

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

OS Lab Manual-1

The document outlines practical exercises for an Operating System Lab at Vidya College of Engineering, covering various algorithms and system calls. It includes implementations of sorting algorithms, CPU scheduling techniques, inter-process communication problems, and UNIX system calls for process and file management. Each practical is accompanied by example programs and descriptions of the algorithms used.

Uploaded by

aakashsaini54573
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 55

VIDYA COLLEGE OF ENGINEERING

MEERUT
Department of Computer Science & Engineering
Operating System Lab
List of Practical
1. Implement following sorting algorithms
a) Insertion Sort
b) Bubble Sort
c) Selection Sort
2. Simulation of following CPU scheduling algorithm.
a) First Come First Serve (FCFS)
b) Shortest Job First (SJF)
3. Simulation of following CPU scheduling algorithm.
c) Priority Scheduling
d) Round Robin Scheduling
4. Execute various UNIX system calls for
a) Process management
b) File management
c) Input/output Systems calls
5. Implementation of Banker’s algorithm
6. Implement the solution for Bounded Buffer (producer-consumer) problem using inter process
communication.
7. Implement the solutions for Readers-Writers problem using inter-process communication
technique -Semaphore.
8. Implement the solution for the dinning philosophers problem for inter process communication.
9. Implementation of contiguous allocation techniques:
a) Worst-Fit
b) Best- Fit
c) First- Fit
10. Implement file storage allocation technique:
d) Contiguous(using array)
e) Linked –list(using linked-list)
f) Indirect allocation (indexing)
Practical 1

Practical Name: Implement following sorting algorithms


a) Insertion Sort
b) Bubble Sort
c) Selection Sort
Description:A Sorting Algorithm is used to rearrange a given array or list elements according to a
comparison operator on the elements. The comparison operator is used to decide the new order of
element in the respective data structure.

Program: Selection Sort + Bubble Sort + Insertion Sort


#include<stdio.h>
#include<conio.h>
void bubble_sort();
void selection_sort();
void insertion_sort();
void main()
{
int m,i,n,a[10];
clrscr();
printf("Enter the no. ofelements");
scanf("%d",&n);
printf("Enter elements");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("Press 1:Selection Sort\nPress 2:Bubble Sort\nPress 3:Insertion Sort\n");
scanf("%d",&m);
switch(m)
{
case 1:selection_sort(a,n);
break;
case 2:bubble_sort(a,n);
break;
case 3:insertion_sort(a,n);
break;
}
getch();
}
void bubble_sort(int *b,int m)
{
int i,j,t;
for(i=0;i<m;i++)
{
for(j=0;j<m-i-1;j++)
{
if(b[j]>b[j+1])
{
t=b[j];
b[j]=b[j+1];
b[j+1]=t;
}
}
}
for(i=0;i<m;i++)
printf("%d ",b[i]);
}

void insertion_sort(int *b,int m)


{
int i,j,t;

for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
if(b[i]<b[j])
{
t=b[j];
b[j]=b[i];
b[i]=t;
}
}
}
for(i=0;i<m;i++)
printf("%d ",b[i]);
}

void selection_sort(int *b,int m)


{
int i,j,t;
for(i=0;i<m;i++)
{
for(j=i+1;j<m;j++)
{
if(b[i]>b[j])
{
t=b[i];
b[i]=b[j];
b[j]=t;
}
}
}

for(i=0;i<m;i++)
printf("%d ",b[i]);
}

Output:
Practical 2

Practical Name: Simulation of following CPU scheduling algorithm.


a) First Come First Serve (FCFS)
b) Shortest Job First (SJF)
Description:These algorithms are either non-preemptive or preemptive. Non-preemptive
algorithms are designed so that once a process enters the running state, it cannot be
preempted until it completes its allotted time, whereas the preemptive scheduling is based on
priority where a scheduler may preempt a low priority running process anytime when a high
priority process enters a ready state.

First Come First Serve (FCFS)

 Jobs are executed on first come, first serve basis.


 It is a non-preemptive, pre-emptive scheduling algorithm.
 Easy to understand and implement.
 Its implementation is based on FIFO queue.
 Poor in performance as average wait time is high.

Shortest Job First (SJF)

 This is a non-preemptive, pre-emptive scheduling algorithm.


 Best approach to minimize waiting time.
 Easy to implement in Batch systems where required CPU time is known in advance.
 Impossible to implement in interactive systems where required CPU time is not
known.
 The processer should know in advance how much time process will take.

Program:
(A) FCFS
#include<stdio.h>
int main()
{
int n,bt[20],wt[20],tat[20],avwt=0,avtat=0,i,j;
printf("Enter total number of processes(maximum 20):");
scanf("%d",&n);
printf("\nEnter Process Burst Time\n");
for(i=0;i<n;i++)
{
printf("P[%d]:",i+1);
scanf("%d",&bt[i]);
}

wt[0]=0;

for(i=1;i<n;i++)
{
wt[i]=0;
for(j=0;j<i;j++)
wt[i]+=bt[j];
}

printf("\nProcess\t\tBurst Time\tWaiting Time\tTurnaround Time");

for(i=0;i<n;i++)
{
tat[i]=bt[i]+wt[i];
avwt+=wt[i];
avtat+=tat[i];
printf("\nP[%d]\t\t%d\t\t%d\t\t%d",i+1,bt[i],wt[i],tat[i]);
}

avwt/=i;
avtat/=i;
printf("\n\nAverage Waiting Time:%d",avwt); printf("\
nAverage Turnaround Time:%d",avtat);
return 0;
}

Output:
(B) SJF
#include<stdio.h>
int main()
{
int bt[20],p[20],wt[20],tat[20],i,j,n,total=0,pos,temp;
float avg_wt,avg_tat;
printf("Enter number of process:");
scanf("%d",&n);

printf("nEnter Burst Time:n");


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

//sorting of burst times


for(i=0;i<n;i++)
{
pos=i;
for(j=i+1;j<n;j++)
{
if(bt[j]<bt[pos])
pos=j;
}

temp=bt[i];
bt[i]=bt[pos];
bt[pos]=temp;
temp=p[i];
p[i]=p[pos];
p[pos]=temp;
}

wt[0]=0;

for(i=1;i<n;i++)
{
wt[i]=0;
for(j=0;j<i;j++)
wt[i]+=bt[j];

total+=wt[i];
}

avg_wt=(float)total/n;
total=0;

printf("nProcesst Burst Time tWaitingTimetTurnaround


Time"); for(i=0;i<n;i++)
{
tat[i]=bt[i]+wt[i];
total+=tat[i];
printf("np%dtt %dtt %dttt%d",p[i],bt[i],wt[i],tat[i]);
}

avg_tat=(float)total/n;
printf("nnAverage Waiting Time=%f",avg_wt);
printf("nAverage Turnaround Time=%fn",avg_tat);
}
Output:
Practical 3

Practical Name: Simulation of following CPU scheduling algorithm.

a) Priority Scheduling
b) Round Robin Scheduling

Description:
Priority Scheduling
Priority scheduling is one of the most common scheduling algorithms in batch systems. Each
process is assigned a priority. Process with the highest priority is to be executed first and so
on.
Processes with the same priority are executed on first come first served basis. Priority can
be decided based on memory requirements, time requirements or any other resource
requirement.
Round robin scheduling
Round Robin is a CPU scheduling algorithm where each process is assigned a fixed time slot
in a cyclic way.
 It is simple, easy to implement, and starvation-free as all processes get fair share
of CPU.
 One of the most commonly used technique in CPU scheduling as a core.
 It is preemptive as processes are assigned CPU only for a fixed slice of time at most.
 The disadvantage of it is more overhead of context switching.

Program:

(a) Priority Scheduling


void main()
{
int i,j,n,t,turn[20],burst[20],p[20],wt[20],c[20];
float await,aturn,twait=0,tturn=0;
printf(“\nEnter the value of n:”);
scanf(“%d”,&n);
printf(“\n Enter the process no burst and arrivaltime”);
for(i=0;i<n;i++)
{
scanf(“%d”,&c[i]);
scanf(“%d”,&burst[i]);
scanf(“%d”,&p[i]);
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
{
if(p[i]>p[j])
{
t=p[i];
p[i]=p[j];
p[j]=t;
t=burst[i];
burst[i]=burst[j];
burst[j]=t;
t=c[i];
c[i]=c[j];
c[j]=t;
}
}
for(i=0;i<n;i++)
{
if(i==0)
{
wt[i]=0;
turn[i]=burst[i];
}
}
else
{
turn[i]=turn[i-1]+burst[i];
wt[i]=turn[i]-burst[i];
twait=twait+wt[i];
tturn=tturn+turn[i];
}await=twait/n;
aturn=tturn/n;
printf(“pno\tbtime\tatime\twtime\tttime”); for(i=0;i<n;i+
+)
{
printf(“\n%d\t%d\t%d\t%d\t%d\n”,c[i],burst[i],p[i],wt[i],turn[i]);
}
printf(“\n The average waiting time is:%f”,await);
printf(“\n The average turn around time is:%f”,aturn);
}

Output:
Enter the process burst no and priority
1 15 2
2 5 1
3 10 3
pnobtimepriority wtimettime
2 5 105
1 152 5 20
3 10 3 20 30
The average waiting time is :8.333333
The average turn around time is:18.333334
(b) Round robin scheduling

struct roundRobin
{
int pburst,pburst1,wtime,endtime,arrivt,boolean,flagcntl;
char pname[5];
}a[5];
int n,tq;
void input();
void initialize();
void calculate();
void display_waittime();
int main()
{
input();
initialize();
calculate();
display_waittime();
//getch();
//return 0;
}
void input()
{ inti;
printf("Enter Total no. of processes\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Enter process name:");
scanf("%s",&a[i].pname);
printf("Enter process burst time:");
scanf("%d",&a[i].pburst);
printf("Enter process arrival time:");
scanf("%d",&a[i].arrivt);
}
printf("\nEnter the time quantum/Time Slice:");
scanf("%d",&tq);
}
void initialize()
{ inti;
for(i=0;i<n;i++)
{
a[i].pburst1=a[i].pburst;
a[i].wtime=0;
a[i].endtime=0;
a[i].boolean=0;
a[i].flagcntl=0;
}
}
void calculate()
{ inti,j=0,k=0,flag=1,count=0;
printf("\n---GANTT CHART---\n");
printf("0 | ");
while(flag)
{
for(i=0;i<n;i++)
{
if((k<n)&&(a[i].arrivt<=count)&&(a[i].flagcntl==0)) //calculating waiting time for
first time
{
a[i].wtime=count-a[i].arrivt;
a[i].endtime=count;
a[i].boolean=1;
a[i].flagcntl=1;
k++;
}
if((a[i].pburst1>tq)&&(a[i].arrivt<=count))
{
if(a[i].boolean==1)
a[i].boolean=0;
else
a[i].wtime=a[i].wtime+(count-a[i].endtime);
count=count+tq;
a[i].pburst1=a[i].pburst1-tq;
a[i].endtime=count;
printf("%d %s| ",count,a[i].pname);
}
else if((a[i].pburst1>0) && (a[i].pburst1<=tq) && (a[i].arrivt<=count))
{
if(a[i].boolean==1)
a[i].boolean=0;
else
a[i].wtime=a[i].wtime+(count-a[i].endtime);
count=count+a[i].pburst1;
a[i].endtime=count;
printf("%d %s| ",count,a[i].pname);
a[i].pburst1=0;
j++;
}
else if(j==n) flag=0;
}
}
}
void display_waittime()
{ inti,tot=0,turn=0;
for(i=0;i<n;i++)
{
printf("\n\nWaiting time for Process %s is %d",a[i].pname,a[i].wtime);
tot=tot+a[i].wtime;
turn=turn+a[i].endtime-a[i].arrivt;
}
printf("\n\n\tAverage waiting time=%f",(float)tot/(float)n);
printf("\n\tAverage turnaround time=%f\n",(float)turn/(float)n);
}

Output:

Enter Total no. of processes


3
Enter process name:A
Enter process burst time:4
Enter process arrival time:0
Enter process name:B
Enter process burst time:3
Enter process arrival time:3
Enter process name:C
Enter process burst time:2
Enter process arrival time:3
Enter the time quantum/Time Slice:2
---GANTT CHART---
0 | 2 A| 4 A| 6 B| 8 C| 9 B|
Waiting time for Process A is 0
Waiting time for Process B is 3
Waiting time for Process C is 3
Average waiting time=2.000000
Average turnaround time=5.000000
Practical 4
Practical Name: Execute Various UNIX system calls for

a) Process Management
b) File Management
c) Input/Output System call

Description: Process Management

Fork System Call:Fork system call is used for creating a new process, which is called child
process, which runs concurrently with the process that makes the fork() call (parent process). After
a new child process is created, both processes will execute the next instruction following the fork()
system call. A child process uses the same pc(program counter), same CPU registers, same open
files which use in the parent process.
It takes no parameters and returns an integer value. Below are different values returned by fork().

Negative Value: creation of a child process was unsuccessful.


Zero: Returned to the newly created child process.
Positive value: Returned to parent or caller. The value contains process ID of newly created child
process.
Example Program 1:

#include <stdio.h>
#include <unistd.h>
int main()
{

// make two process which run same


// program after this instruction
fork();

printf("Hello world!\n");
return 0;
}

Output:
Hello world!
Hello world!

Example Program 2:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void forkexample()
{
// child process because return value zero
if (fork() == 0)
printf("Hello from Child!\n");

// parent process because return value non-zero.


else
printf("Hello from Parent!\n");
}
int main()
{
forkexample();
return 0;
}

Output: In the above code, a child process is created. fork() returns 0 in the child process and positive
integer in the parent process.
Here, two outputs are possible because the parent process and child process are running concurrently. So
we don’t know whether the OS will first give control to the parent process or the child process.

Hello from Child!


Hello from Parent!
OR
Hello from Parent!
Hello from Child!

Example Program 3:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

void forkexample()
{
int x = 1;

if (fork() == 0)
printf("Child has x = %d\n", ++x);
else
printf("Parent has x = %d\n", --x);
}
int main()
{
forkexample();
return 0;
}

Output:Here, global variable change in one process does not affected two other processes because
data/state of two processes are different. And also parent and child run simultaneously so two outputs
are possible.

Parent has x = 0
Child has x = 2
(or)
Child has x = 2
Parent has x = 0

Process ID:System Callpid_t getpid (void) : It returnsthe process's ID number.


System Call: pid_t getppid (void) : It returns the parent process's ID number.
Program:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

void main ()
{
int pid;
printf ("I'm the original process with Process id: %d and my parent id is: %d.\n",
getpid (), getppid ());
pid = fork (); /* Duplicate. Child and parent continue from here */
if (pid != 0) /* pid is non-zero, so I must be the parent */
{
printf ("I'm the parent process with process id %d and my parent id is %d.\n",
getpid (), getppid ());
printf ("My child's process id is %d\n", pid);
}
else /* pid is zero, so I must be the child */
{
printf ("I'm the child process with process id %d and my parent id is %d.\n",
getpid (), getppid ());
}
printf("Process with process id %d terminates.\n",getpid ());/*Both procs execute this */
}

Output:
I'm the original process with Process id: 3514 and my parent id is: 1923.
I'm the parent process with process id 3514 and my parent id is 1923.
My child's process id is 3515
Process with process id 3514 terminates.
I'm the child process with process id 3515 and my parent id is 3514.
Process with process id 3515 terminates.

Orphan Process:A process whose parent process no more exists i.e. either finished or terminated
without waiting for its child process to terminate is called an orphan process. In the following code,
parent finishes execution and exits while the child process is still executing and is called an orphan
process now. However, the orphan process is soon adopted by init process, once its parent process
dies.
Note: Insert some code, e.g., a sleep() command into the child to ensure that parent finished first

Program:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

void main ()
{
int pid;
printf ("I'm the original process with Process id: %d and my parent id is: %d.\n",
getpid (), getppid ());
pid = fork (); /* Duplicate. Child and parent continue from here */
if (pid != 0) /* pid is non-zero, so I must be the parent */
{
printf ("I'm the parent process with process id %d and my parent id is %d.\n",
getpid (), getppid ());
printf ("My child's process id is %d\n", pid);
}
else /* pid is zero, so I must be the child */
{
sleep(1);
printf ("I'm the child process with process id %d and my parent id is %d.\n",
getpid (), getppid ());
}
printf("Process with process id %d terminates.\n",getpid ());/*Both procs execute this */
}

Output:
I'm the original process with Process id: 3608 and my parent id is: 1923.
I'm the parent process with process id 3608 and my parent id is 1923.
My child's process id is 3609
Process with process id 3608 terminates.
sanjiv@sanjiv-HP-Notebook:~$ I'm the child process with process id 3609 and my parent id is
2087.
Process with process id 3609 terminates.

Process Termination: System Call: void exit (int status).


exit () closes all of a process's file descriptors, deallocates its code, data, and stack, and then
terminates the process. When a child process terminates, it sends its parent a SIGCHLD signal and
waits for its termination code status to be accepted. Only the lower eight bits of status are used, so
values are limited to 0255. The kernel ensures that all of a terminating process's children are
orphaned and adopted by "init" by setting their PPID to 1. The "init" process always accepts its
children's termination codes. exit () never returns
A call to wait() blocks the calling process until one of its child processes exits or a signal is
received. After child process terminates, parent continues its execution after wait system call
instruction.
Child process may terminate due to any of these:
 It calls exit();
 It returns (an int) from main
 It receives a signal (from the OS or another process) whose default action is to terminate.

Program:

#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>

int main()
{
int pid = fork ();
printf("Process id of the child process is: %d\n",pid);

if (pid== 0) {
printf("Child Process is going to sleep \n");

sleep(30);
exit(1);
printf("Child process is awaken now \n");
}
else
{
printf("HP: hello from parent process\n");
printf("Parent is waitng for termination of child process\n");
wait(NULL);
printf("Now child process has terminated\n");
}

printf("Bye\n");
return 0;
}

Output:
Process id of the child process is: 5906
HP: hello from parent process
Parent is waitng for termination of child process
Process id of the child process is: 0
Child Process is going to sleep
Now child process has terminated
Bye
Description: File Management
The file structure related system calls available in the UNIX system let you create, open, and close
files, read and write files, randomly access files, alias and remove files, get information about files,
check the accessibility of files, change protections, owner, and group of files, and control devices.
These operations either use a character string that defines the absolute or relative path name of a
file, or a small integer called a file descriptor that identifies the I/O channel.
A channel is a connection between a process and a file that appears to the process as an unformatted
stream of bytes. The kernel presents and accepts data from the channel as a process reads and
writes thatchannel. To a process then, all input and output operations are synchronous and
unbuffered.
When doing I/O, a process specifies the file descriptor for an I/Ochannel, a buffer to be filled or
emptied, and the maximum size of data to be transferred. An I/O channel may allow input, output,
or both. Furthermore, each channel has a read/write pointer. Each I/O operation starts where the
last operation finished and advances the pointer by thenumber of bytes transferred. A process can
access a channel's data randomly by changing the read/write pointer.
All input and output operations start by opening a file using either the "creat()" or "open()" system
calls. These calls return a file descriptor that identifies the I/O channel. Recall that file descriptors
0, 1, and 2 refer to standard input, standard output, and standard error files respectively, and that file
descriptor 0 is a channel to your terminal's keyboard and file descriptors 1 and 2 arechannels to your
terminal's display screen.

Creat() System Call: The prototype for the creat() system call is:

int creat(file_name, mode)


char *file_name;
int mode;

where file_name is pointer to a null terminated character string that names the file and mode defines
the file's access permissions. The mode is usually specified as an octal number such as 0666 that
would mean read/write permission for owner, group, and others or the mode may also be entered
using manifest constants defined in the "/usr/include/sys/stat.h" file. If the file named by file_name
does not exist, the UNIX system creates it with the specified mode permissions. However, if the file
does exist, its contents are discarded and the mode value is ignored. The permissions of the existing
file are retained.

Program:
#include <stdio.h>
#include <sys/stat.h> /* defines S_IREAD & S_IWRITE */
#include<unistd.h>
#include <fcntl.h> /* open(), creat() - and fcntl() */
#include <stdlib.h>

int main()
{
int fd;
fd = creat("datafile.dat", S_IREAD |
S_IWRITE); if (fd == -1)
printf("Error in opening datafile.dat\n");
else
{
printf("datafile.dat opened for read/write access\n");
printf("datafile.dat is currently empty\n");
}
close(fd);
exit (0);
}

Output:
datafile.dat opened for read/write access
datafile.dat is currently empty

The following is a sample of the manifest constants for the mode argument as defined in
/usr/include/sys/stat.h:
Multiple mode values may be combined by or'ing (using the | operator) the values together as
demonstrated in the above sample program.

#define S_IRWXU 0000700 /* -rwx------*/


#define S_IREAD 0000400 /* read permission, owner */
#define S_IRUSR S_IREAD
#define S_IWRITE 0000200 /* write permission, owner */
#define S_IWUSR S_IWRITE
#define S_IEXEC 0000100 /* execute/search permission, owner */
#define S_IXUSR S_IEXEC
#define S_IRWXG 0000070 /* ----rwx- - -*/
#define S_IRGRP 0000040 /* read permission, group */
#define S_IWGRP 0000020 /* write "" */
#define S_IXGRP 0000010 /* execute/search "" */
#define S_IRWXO 0000007 /*-------rwx */
#define S_IROTH 0000004 /* read permission, other */
#define S_IWOTH 0000002 /* write "" */
#define S_IXOTH 0000001 /* execute/search "" */

open() System Call: open() lets you open a file for reading, writing, or reading and writing.

The prototype for the open() system call is:


#include <fcntl.h>
int open(file_name, option_flags [, mode])
char *file_name;
int option_flags, mode;

where file_name is a pointer to the character string that names the file, option_flags represent
the type of channel, and mode defines the file's access permissions if the file is being created.

The allowable option_flags as defined in "/usr/include/fcntl.h" are:

#define O_RDONLY 0 /* Open the file for reading only */


#define O_WRONLY 1 /* Open the file for writing only */
#define O_RDWR 2 /* Open the file for both reading and writing*/
#define O_NDELAY 04 /* Non-blocking I/O */
#define O_APPEND 010 /* append (writes guaranteed at the end) */
#define O_CREAT 00400 /*open with file create (uses third open arg) */
#define O_TRUNC 01000 /* open with truncation */
#define O_EXCL 02000 /* exclusive open */
Multiple values are combined using the | operator (i.e. bitwise OR).
Note: some combinations are mutually exclusive such as: O_RDONLY |O_WRONLY and will
cause open() to fail. If the O_CREAT flag is used,then a mode argument is required. The mode
argument may be specified in the same manner as in the creat() system call.

Program:

#include <stdio.h>
#include <sys/stat.h> /* defines S_IREAD & S_IWRITE */
#include<unistd.h>
#include <fcntl.h> /* open(), creat() - and fcntl() */
#include <stdlib.h>

static char message[] = "Hello, world";

int main()
{
int fd;
char buffer[80];

/* open datafile.dat for read/write access (O_RDWR)


create datafile.dat if it does not exist (O_CREAT)
return error if datafile already exists (O_EXCL)
permit read/write access to file (S_IWRITE | S_IREAD)
*/
fd = open("datafile.dat",O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
if (fd != -1)
{
printf("datafile.dat opened for read/write access\n");
write(fd, message, sizeof(message));
lseek(fd, 0L, 0); /* go back to the beginning of the file */
if (read(fd, buffer, sizeof(message)) == sizeof(message))
printf("\"%s\" was written to datafile.dat\n", buffer);
else
printf("*** error reading datafile.dat ***\n");
close (fd);
}
else
printf("*** datafile.dat already exists ***\n");
exit (0);
}

close() System Call: To close a channel, use the close() system call. The prototype for the close()
system call is:

int close(file_descriptor)
int file_descriptor;

where file_descriptor identifies a currently open channel. Close() fails if file_descriptor does
not identify a currently open channel.
Read() and write() System Call: The read() system call does all input and the write() system call
does all output. When used together, they provide all the tools necessary to do input and output
sequentially. When used with the lseek() system call, they provide all the tools necessary to do
input and output randomly.

Both read() and write() take three arguments. Their prototypes are:

int read(file_descriptor, buffer_pointer, transfer_size)


int file_descriptor;
char *buffer_pointer;
unsigned transfer_size;

int write(file_descriptor, buffer_pointer, transfer_size)


int file_descriptor;
char *buffer_pointer;
unsigned transfer_size;

where file_descriptor identifies the I/O channel, buffer_pointer points to the area in memory where
the data is stored for a read() or where the data is taken for a write(), and transfer_size defines the
maximum number of characters transferred between the file and the buffer. read() and write()
return the number of bytes transferred.
There is no limit on transfer_size, but you must make sure it's safe to copy transfer_size bytes to or
from the memory pointed to bybuffer_pointer. A transfer_size of 1 is used to transfer a byte at
atime for so-called "unbuffered" input/output. The most efficient value for transfer_size is the size
of the largest physical record the I/O channel is likely to have to handle. Therefore, 1K bytes -- the
disk block size -- is the most efficient general-purpose buffer size for a standard file. However, if
you are writing to a terminal, the transfer is best handled in lines ending with a newline.

Program:
#include <stdio.h>
#include <sys/stat.h> /* defines S_IREAD & S_IWRITE */
#include<unistd.h>
#include <fcntl.h> /* open(), creat() - and fcntl() */
#include <stdlib.h>

static char message[] = "Hello, world";

int main()
{
int fd;
char buffer[80];

/* open datafile.dat for read/write access (O_RDWR)


create datafile.dat if it does not exist (O_CREAT)
return error if datafile already exists (O_EXCL)
permit read/write access to file (S_IWRITE | S_IREAD)
*/
fd = open("datafile.dat",O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
if (fd != -1)
{
printf("datafile.dat opened for read/write access\n");
write(fd, message, sizeof(message));
lseek(fd, 0L, 0); /* go back to the beginning of the file */
if (read(fd, buffer, sizeof(message)) == sizeof(message))
printf("\"%s\" was written to datafile.dat\n", buffer);
else
printf("*** error reading datafile.dat ***\n");
close (fd);
}
else
printf("*** datafile.dat already exists ***\n");
exit (0);
}

lseek() System Call:The UNIX system file system treats an ordinary file as a sequence of bytes.
No internal structure is imposed on a file by the operating system. Generally, a file is read or
written sequentially -- that is, from beginning to the end of the file. Sometimes sequential reading
and writing is not appropriate. It may be inefficient, for instance, to read an entire file just to move
to the end of the file to add characters. Fortunately, the UNIX system lets you read and write
anywhere in the file. Known as "random access", this capability is made possible with the lseek()
system call. During file I/O, the UNIX system uses a long integer, also called a File Pointer, to
keep track of the next byte to read or write. This long integer represents the number of bytes from
the beginning of the file to that next character. Random access I/O is achieved by changing the
value of this file pointer using the lseek() system call.
The prototype for lseek() is:

long lseek(file_descriptor, offset, whence)


int file_descriptor;
long offset;
int whence;

where file_descriptor identifies the I/O channel and offset and whence work together to describe
how to change the file pointer according to the following table:

whence new position


0 offset bytes into the file
1 current position in the file plus offset
2 current end-of-file position plus offset

If successful, lseek() returns a long integer that defines the new file pointer value measured in bytes
from the beginning of the file. If unsuccessful, the file position does not change. Certain devices
are incapable of seeking, namely terminals and the character interface to a tape drive. lseek() does
not change the file pointer to these devices.

Program:
#include <stdio.h>
#include <sys/stat.h> /* defines S_IREAD & S_IWRITE */
#include<unistd.h>
#include <fcntl.h> /* open(), creat() - and fcntl() */
#include <stdlib.h>
int main()
{
int fd;
long position;

fd = open("datafile.dat", O_RDONLY);
if ( fd != -1)
{
position = lseek(fd, 0L, 2); /* seek 0 bytes from end-of-file */
if (position != -1)
printf("The length of datafile.dat is %ld bytes.\n", position);
else
perror("lseek error");
}
else
printf("can't open datafile.dat\n");
close(fd);
}

Output: The length of datafile.dat is 12 bytes


Practical 5

Practical Name: Implementation of Banker‟s algorithm

Description: The banker‟s algorithm is a resource allocation and deadlock avoidance algorithm
that tests for safety by simulating the allocation for 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.
Following Data structures are used to implement the Banker‟s Algorithm:
Let ‘n’ be the number of processes in the system and ‘m’ be the number of resources types.
Available:
 It is a 1-d array of size ‘m’ indicating the number of available resources of each type.
 Available[ j ] = k means there are ‘k’ instances of resource type Rj
Max:
 It is a 2-d array of size „n*m’ that defines the maximum demand of each process in
a system.
 Max[ i, j ] = k means process Pi may request at most ‘k’ instances of resource type Rj.
Allocation:
 It is a 2-d array of size ‘n*m’ that defines the number of resources of each type currently
allocated to each process.
 Allocation[ i, j ] = k means process Pi is currently allocated ‘k’ instances of resource
type Rj
Need:
 It is a 2-d array of size ‘n*m’ that indicates the remaining resource need of each process.
 Need [ i, j ] = k means process Pi currently need ‘k’ instances of resource type Rj
for its execution.
 Need [ i, j ] = Max [ i, j ] – Allocation [ i, j ]

Allocationi specifies the resources currently allocated to process Pi and Needi specifies the
additional resources that process Pi may still request to complete its task.
Banker‟s algorithm consists of Safety algorithm and Resource request algorithm
Safety Algorithm
The algorithm for finding out whether or not a system is in a safe state can be described as
follows:
1) Let Work and Finish be vectors of length „m‟ and „n‟
respectively. Initialize: Work = Available
Finish[i] = false; for i=1, 2, 3, 4….n
2) Find an i such that both
a) Finish[i] = false
b) Needi <= Work
if no such i exists goto step (4)
3) Work = Work + Allocation[i]
Finish[i] = true
goto step (2)
4) if Finish [i] = true for all i
then the system is in a safe state
Resource-Request Algorithm
Let Requesti be the request array for process Pi. Requesti [j] = k means process Pi wants k
instances of resource type Rj. When a request for resources is made by process Pi, the following
actions are taken:
1) If Requesti <= Needi
Goto step (2) ; otherwise, raise an error condition, since the process has exceeded its maximum
claim.
2) If Requesti <= Available
Goto step (3); otherwise, Pi must wait, since the resources are not available.
3) Have the system pretend to have allocated the requested resources to process Pi by modifying
the state as
follows:
Available = Available – Requesti
Allocationi = Allocationi + Requesti
Needi = Needi– Requesti
Example:
Considering a system with five processes P0 through P4 and three resources of type A, B, C.
Resource type A has 10 instances, B has 5 instances and type C has 7 instances. Suppose at
time t0 following snapshot of the system has been taken:

Question 1. What will be the content of the Need matrix?


Need [i, j] = Max [i, j] – Allocation [i, j]
So, the content of Need Matrix is:

Question2. Is the system in a safe state? If Yes, then what is the safe sequence?
Applying the Safety algorithm on the given system,
Question3. What will happen if process P1 requests one additional instance of resource type
A and two instances of resource type C?

We must determine whether this new system state is safe. To do so, we again execute Safety
algorithm on the above data structures.
Hence the new system state is safe, so we can immediately grant the request for process P1 .

Program to illustrate Banker's Algorithm

#include<stdio.h>
#include<iostream.h>

// Number of processes
int P = 5;

// Number of
resources int R = 3;

// Function to find the need of each process


void calculateNeed(int need[P][R], int maxm[P][R], int allot[P][R])
{
// Calculating Need of each P
for (int i = 0 ; i < P ; i++)
for (int j = 0 ; j < R ; j++)
// Need of instance = maxm instance – allocated instance
need[i][j] = maxm[i][j] - allot[i][j];
}
// Function to find the system is in safe state or not
bool isSafe(int processes[], int avail[], int maxm[][R], int allot[][R])
{
int need[P][R];

// Function to calculate need matrix


calculateNeed(need, maxm, allot);

// Mark all processes as infinish


bool finish[P] = {0};

// To store safe sequence


int safeSeq[P];

// Make a copy of available


resources int work[R];
for (int i = 0; i < R ; i++)
work[i] = avail[i];

// While all processes are not finished


// or system is not in safe
state. int count = 0;
while (count < P)
{
// Find a process which is not finish and
// whose needs can be satisfied with current
// work[] resources.
bool found = false;
for (int p = 0; p < P; p++)
{
// First check if a process is finished,
// if no, go for next condition
if (finish[p] == 0)
{
// Check if for all resources of
// current P need is less
// than work
int j;
for (j = 0; j < R; j++)
if (need[p][j] > work[j])
break;

// If all needs of p were satisfied.


if (j == R)
{
// Add the allocated resources of
// current P to the available/work
// resources i.e.free the resources
for (int k = 0 ; k < R ; k++)
work[k] += allot[p][k];

// Add this process to safe


sequence. safeSeq[count++] = p;

// Mark this p as finished


finish[p] = 1;

found = true;
}
}
}

// If we could not find a next process in safe


// sequence.
if (found == false)
{
Printf("System is not in safe state");
return false;
}
}

// If system is in safe state then


// safe sequence will be as below
Printf("System is in safe state.\nSafe"
" sequence is: ");
for (int i = 0; i < P ; i++)
printf(“%d” , safeSeq[i]);

return true;
}

// Driver code
int main()
{
int processes[] = {0, 1, 2, 3, 4};

// Available instances of resources


int avail[] = {3, 3, 2};

// Maximum R that can be allocated


// to processes
int maxm[][R] = {{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3}};

// Resources allocated to processes


int allot[][R] = {{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}};

// Check system is in safe state or not


isSafe(processes, avail, maxm, allot);

return 0;
}

OUTPUT:

System is in safe state.


Safe sequence is: 1 3 4 0 2
Practical 6
Practical Name: Implement the solution for Bounded Buffer (producer-consumer) problem using
inter process communication.
Description: In computing, the producer–consumer problem (also known as the bounded-buffer
problem) is a classic example of a multi-process synchronization problem. The problem
describes two processes, the producer and the consumer, which share a common, fixed-size
buffer used as a queue.

 The producer‟s job is to generate data, put it into the buffer, and start again.
 At the same time, the consumer is consuming the data (i.e. removing it from the buffer),
one piece at a time.
Problem : To make sure that the producer won‟t try to add data into the buffer if it‟s full and
that the consumer won‟t try to remove data from an empty buffer.

Solution : The producer is to either go to sleep or discard data if the buffer is full. The next time
the consumer removes an item from the buffer, it notifies the producer, who starts to fill the
buffer again. In the same way, the consumer can go to sleep if it finds the buffer to be empty.
The next time the producer puts data into the buffer, it wakes up the sleeping consumer.
An inadequate solution could result in a deadlock where both processes are waiting to be
awakened.
In the post Producer-Consumer solution, we have discussed above solution by using inter-thread
communication(wait(), notify(), sleep()). In this post, we will use Semaphores to implement the
same.
The below solution consists of four classes:
1. Q : the queue that you‟re trying to synchronize
2. Producer : the threaded object that is producing queue entries
3. Consumer : the threaded object that is consuming queue entries
4. PC : the driver class that creates the single Q, Producer, and Consumer.

Program to illustrate Producer Consumer Algorithm

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

int buf[256];
int in = 0;
int out = 0;
sem_t full;
sem_t empty;
sem_t mutex;
int buf_size;
int counter = 0;

void *producer(void *arg)


{
int i, item, *index;
index = (int *)arg;
for (i = 0;; i++)
{
item = 1000 + i;
sem_wait(&empty);
sem_wait(&mutex);
buf[in] = item;
in = (in + 1) % (*index);
counter++;
printf("\n%d [P%d] ", item, *index);
sem_post(&mutex);
sem_post(&full);
/* if (i % 5 == 0)
sleep(1); */
}
}

void *consumer(void *arg)


{
int i, item, *index;
index = (int *)arg;
for (i = 0;;i++)
{
sem_wait(&full);
sem_wait(&mutex);
item = buf[out];
out = (out + 1) % (*index);
counter--;
printf("\n%d [C%d] ", item, *index);
sem_post(&mutex);
sem_post(&empty);
/* if (i % 5 == 0)
sleep(1); */
}
}

int main()
{
int produce, consume;
int i;
printf("\nThe Buffer Size:");
scanf("%d", &buf_size);
printf("\nThe Producer:");
scanf("%d", &produce);
printf("\nThe Consumer:");
scanf("%d", &consume);
pthread_t prod, cons;
void* exit_status;
sem_init(&full, 0, 0);
sem_init(&empty, 0, buf_size);
sem_init(&mutex, 0, 1);
for (i = 0; i < produce; i++)
{
pthread_create(&prod, NULL, producer, &i);
}
for (i = 0; i < consume; i++)
{
pthread_create(&cons, NULL, consumer, &i);
}
pthread_join(prod, &exit_status);
pthread_join(cons, &exit_status);
// pthread_exit(NULL);
return 0;
}

Output:
Producer produced item : 0
Consumer consumed item : 0
Producer produced item : 1
Consumer consumed item : 1
Producer produced item : 2
Consumer consumed item : 2
Producer produced item : 3
Consumer consumed item : 3
Producer produced item : 4
Consumer consumed item : 4
Practical 7
Practical Name: Implement the solutions for Readers-Writers problem using inter-process
communication technique -Semaphore.
Description: Consider a situation where we have a file shared between many people.

 If one of the people tries editing the file, no other person should be reading or writing
at the same time, otherwise changes will not be visible to him/her.
 However if some person is reading the file, then others may read it at the same
time. Precisely in OS we call this situation as the readers-writers problem
Problem parameters:
 One set of data is shared among a number of processes
 Once a writer is ready, it performs its write. Only one writer may write at a time
 If a process is writing, no other process can read it
 If at least one reader is reading, no other process can write
 Readers may not write and only read
Solution when Reader has the Priority over Writer
Here priority means, no reader should wait if the share is currently opened for reading.
Three variables are used: mutex, wrt, readcnt to implement solution
1. semaphore mutex, wrt; // semaphore mutex is used to ensure mutual exclusion
when readcnt is updated i.e. when any reader enters or exit from the critical section and
semaphore wrt is used by both readers and writers
2. int readcnt; // readcnt tells the number of processes performing read in the critical
section, initially 0
Functions for sempahore :
– wait() : decrements the semaphore value.
– signal() : increments the semaphore value.
Writer process:
1. Writer requests the entry to critical section.
2. If allowed i.e. wait() gives a true value, it enters and performs the write. If not allowed, it
keeps on waiting.
3. It exits the critical section.

Implement Readers Writer Problem.

#include<stdio.h>
#include<conio.h>
#include<stdbool.h>
struct semaphore
{
int mutex;
int rcount;
int rwait;
bool wrt;
};
void addR(struct semaphore *s)
{
if (s->mutex == 0 && s->rcount == 0)
{
printf("\nSorry, File open in Write mode.\nNew Reader added to queue.\n");
s->rwait++;
}
Else {

printf("\nReader Process added.\n");


s->rcount++;
s->mutex--;
}
return ;
}
void addW(struct semaphore *s)
{
if(s->mutex==1)
{
s->mutex--;
s->wrt=1;
printf("\nWriter Process added.\n");
}
else if(s->wrt) printf("\nSorry, Writer already operational.\n");
else printf("\nSorry, File open in Read mode.\n");
return ;
}
void remR(struct semaphore *s)
{
if(s->rcount == 0) printf("\nNo readers to remove.\n");
else
{
printf("\nReader Removed.\n");
s->rcount--;
s->mutex++;

}
return ;
}
void remW(struct semaphore *s)
{
if(s->wrt==0) printf("\nNo Writer to Remove");
else
{
printf("\nWriter Removed\n");
s->mutex++;
s->wrt=0;
if(s->rwait!=0)
{
s- >mutex-=s->rwait;
s->rcount=s->rwait;
s->rwait=0;
printf("%d waiting Readers Added.",s->rcount);
}
}
}
int main()
{
struct semaphore S1={1,0,0};
while(1)
{
//system("cls");
printf("Options :-\n1.Add Reader.\n2.Add Writer.\n3.Remove Reader.\n4.Remove
Writer.\n5.Exit.\n\n\tChoice : ");
int ch;
scanf("%d",&ch);
switch(ch)
{

case 1: addR(&S1); break;

case 2: addW(&S1); break;

case 3: remR(&S1); break;


case 4: remW(&S1); break;
case 5: printf("\n\tGoodBye!"); getch(); return 0;
default: printf("\nInvalid Entry!"); continue;
}
printf("\n\n<<<<<< Current Status >>>>>>\n\n\tMutex\t\t:\t%d\n\tActive Readers\t:\t%d\n\
tWaiting Readers\t:\t%d\n\tWriter Active\t:\t%s\n\n", S1.mutex, S1.rcount, S1.rwait,
(S1.mutex==0 && S1.rcount==0) ? "YES" : "NO");
system("pause");
}}

OUTPUT
File open in Write mode
New reader added to queue
Practical 8

Practical Name : Implement the solution for the dinning philosophers problem for inter process
communication.

Description: The dining-philosophers problem is considered a classic synchronization problem


because it is an example of a large class of concurrency-control problems. It is a simple
representation of the need to allocate several resources among several processes in a deadlock-
free and starvation-free manner. Consider five philosophers who spend their lives thinking and
eating. The philosophers share a circular table surrounded by five chairs, each belonging to one
philosopher. In the center of the table is a bowl of rice, and the table is laid with five single
chopsticks. When a philosopher thinks, she does not interact with her colleagues. From time to
time, a philosopher gets hungry and tries to pick up the two chopsticks that are closest to her (the
chopsticks that are between her and her left and right neighbors). A philosopher may pick up
only one chopstick at a time. Obviously, she cam1ot pick up a chopstick that is already in the
hand of a neighbor. When a hungry philosopher has both her chopsticks at the same time, she
eats without releasing her chopsticks. When she is finished eating, she puts down both of her
chopsticks and starts thinking again. The dining-philosophers problem may lead to a deadlock
situation and hence some rules have to be framed to avoid the occurrence of deadlock.

Program:

#include<stdio.h>

#define n 4

int compltedPhilo = 0,i;

struct fork{
int taken;
}ForkAvil[n];

struct philosp{
int left;
int right;
}Philostatus[n];

void goForDinner(int philID){ //same like threads concept here cases implemented
if(Philostatus[philID].left==10 && Philostatus[philID].right==10)
printf("Philosopher %d completed his dinner\n",philID+1);
//if already completed dinner
else if(Philostatus[philID].left==1 && Philostatus[philID].right==1){
//if just taken two forks
printf("Philosopher %d completed his dinner\n",philID+1);
Philostatus[philID].left = Philostatus[philID].right = 10; //remembering that he completed
dinner by assigning value 10
int otherFork = philID-1;

if(otherFork== -1)
otherFork=(n-1);

ForkAvil[philID].taken = ForkAvil[otherFork].taken = 0; //releasing forks


printf("Philosopher %d released fork %d and fork %d\n",philID+1,philID+1,otherFork+1);
compltedPhilo++;
}
else if(Philostatus[philID].left==1 && Philostatus[philID].right==0){ //left already taken, trying
for right fork
if(philID==(n-1)){
if(ForkAvil[philID].taken==0){ //KEY POINT OF THIS PROBLEM, THAT
LAST PHILOSOPHER TRYING IN reverse DIRECTION
ForkAvil[philID].taken = Philostatus[philID].right = 1;
printf("Fork %d taken by philosopher %d\n",philID+1,philID+1);
}else{
printf("Philosopher %d is waiting for fork %d\n",philID+1,philID+1);
}
}else{ //except last philosopher case
int dupphilID = philID;
philID-=1;

if(philID== -1)
philID=(n-1);

if(ForkAvil[philID].taken == 0){
ForkAvil[philID].taken = Philostatus[dupphilID].right = 1;
printf("Fork %d taken by Philosopher %d\n",philID+1,dupphilID+1);
}else{
printf("Philosopher %d is waiting for Fork %d\n",dupphilID+1,philID+1);
}
}
}
else if(Philostatus[philID].left==0){ //nothing taken
yet if(philID==(n-1)){
if(ForkAvil[philID-1].taken==0){ //KEY POINT OF THIS PROBLEM, THAT LAST
PHILOSOPHER TRYING IN reverse DIRECTION
ForkAvil[philID-1].taken = Philostatus[philID].left = 1;
printf("Fork %d taken by philosopher %d\n",philID,philID+1);
}else{
printf("Philosopher %d is waiting for fork %d\n",philID+1,philID);
}
}else{ //except last philosopher case
if(ForkAvil[philID].taken == 0){
ForkAvil[philID].taken = Philostatus[philID].left = 1;
printf("Fork %d taken by Philosopher %d\n",philID+1,philID+1);
}else{
printf("Philosopher %d is waiting for Fork %d\n",philID+1,philID+1);
}
}
}else{}
}

int main(){
for(i=0;i<n;i++)
ForkAvil[i].taken=Philostatus[i].left=Philostatus[i].right=0;

while(compltedPhilo<n){
/* Observe here carefully, while loop will run until all philosophers complete dinner
Actually problem of deadlock occur only thy try to take at same time
This for loop will say that they are trying at same time. And remaining status will
print by go for dinner function
*/
for(i=0;i<n;i++)
goForDinner(i);
printf("\nTill now num of philosophers completed dinner are %d\n\n",compltedPhilo);
}

return 0;
}
Output
Fork 1 taken by Philosopher 1
Fork 2 taken by Philosopher 2
Fork 3 taken by Philosopher 3
Philosopher 4 is waiting for fork 3
Till now num of philosophers completed dinner are 0
Fork 4 taken by Philosopher 1
Philosopher 2 is waiting for Fork 1
Philosopher 3 is waiting for Fork 2
Philosopher 4 is waiting for fork 3
Till now num of philosophers completed dinner are 0
Philosopher 1 completed his dinner
Philosopher 1 released fork 1 and fork 4
Fork 1 taken by Philosopher 2
Philosopher 3 is waiting for Fork 2
Philosopher 4 is waiting for fork 3
Till now num of philosophers completed dinner are 1
Philosopher 1 completed his dinner
Philosopher 2 completed his dinner
Philosopher 2 released fork 2 and fork 1
Fork 2 taken by Philosopher 3
Philosopher 4 is waiting for fork 3
Till now num of philosophers completed dinner are 2
Philosopher 1 completed his dinner
Philosopher 2 completed his dinner
Philosopher 3 completed his dinner
Philosopher 3 released fork 3 and fork 2
Fork 3 taken by philosopher 4
Till now num of philosophers completed dinner are 3
Philosopher 1 completed his dinner
Philosopher 2 completed his dinner
Philosopher 3 completed his dinner
Fork 4 taken by philosopher 4
Till now num of philosophers completed dinner are 3
Philosopher 1 completed his dinner
Philosopher 2 completed his dinner
Philosopher 3 completed his dinner
Philosopher 4 completed his dinner
Philosopher 4 released fork 4 and fork 3
Till now num of philosophers completed dinner are 4
Practical 9

Program Name: Implementation of contiguous allocation techniques:

a) Worst –fit
b) Best-fit
c) First-fit

Description: One of the simplest methods for memory allocation is to divide memory into
several fixed-sized partitions. Each partition may contain exactly one process. In this multiple-
partition method, when a partition is free, a process is selected from the input queue and is
loaded into the free partition. When the process terminates, the partition becomes available for
another process. The operating system keeps a table indicating which parts of memory are
available and which are occupied. Finally, when a process arrives and needs memory, a memory
section large enough for this process is provided. When it is time to load or swap a process into
main memory, and if there is more than one free block of memory of sufficient size, then the
operating system must decide which free block to allocate. Best-fit strategy chooses the block
that is closest in size to the request. First-fit chooses the first available block that is large
enough. Worst-fit chooses the largest available block.

Program for First Fit Algorithm in C

#include<stdio.h>
void main( )
{ int bsize[10], psize[10], bno, pno, flags[10], allocation[10], i, j;
for(i = 0; i < 10; i++)
{
flags[i] = 0;
allocation[i] = -1;
}
printf("Enter no. of blocks: ");
scanf("%d", &bno);
printf("\nEnter size of each block: ");
for(i = 0; i < bno; i++)
scanf("%d", &bsize[i]);
printf("\nEnter no. of processes: ");
scanf("%d", &pno);
printf("\nEnter size of each process: ");
for(i = 0; i < pno; i++)
scanf("%d", &psize[i]);
for(i = 0; i < pno; i++) //allocation as per first fit
for(j = 0; j < bno; j++)
if(flags[j] == 0 && bsize[j] >= psize[i])
{
allocation[j] = i;
flags[j] = 1;
break;
}
//display allocation details
printf("\nBlock no.\tsize\t\tprocess no.\t\tsize");
for(i = 0; i < bno; i++)
{ printf("\n%d\t\t%d\t\t", i+1, bsize[i]);
if(flags[i] == 1)
printf("%d\t\t\t%d",allocation[i]+1,psize[allocation[i]]);
else
printf("Not allocated");
}}

Program for Best Fit Algorithm in C:

#include<stdio.h>
void main()
{
int fragment[20],b[20],p[20],i,j,nb,np,temp,lowest=9999;
static int barray[20],parray[20];

printf("\n\t\t\tMemory Management Scheme - Best Fit");


printf("\nEnter the number of blocks:");
scanf("%d",&nb);
printf("Enter the number of processes:");
scanf("%d",&np);

printf("\nEnter the size of the blocks:-\n");


for(i=1;i<=nb;i++)
{
printf("Block no.%d:",i);
scanf("%d",&b[i]);
}

printf("\nEnter the size of the processes :-\n");


for(i=1;i<=np;i++)
{
printf("Process no.%d:",i);
scanf("%d",&p[i]);
}

for(i=1;i<=np;i++)
{
for(j=1;j<=nb;j++)
{
if(barray[j]!=1)
{
temp=b[j]-p[i];
if(temp>=0)
if(lowest>temp)
{
parray[i]=j;
lowest=temp;
}}}

fragment[i]=lowest;
barray[parray[i]]=1;
lowest=10000; }

printf("\nProcess_no\tProcess_size\tBlock_no\tBlock_size\tFragment");
for(i=1;i<=np && parray[i]!=0;i++)
printf("\n%d\t\t%d\t\t%d\t\t%d\t\t%d",i,p[i],parray[i],b[parray[i]],fragment[i]);
}

Program for Worst Fit Algorithm in C

#include<stdio.h>

int main()
{
int fragments[10], blocks[10], files[10];
int m, n, number_of_blocks, number_of_files, temp, top = 0;
static int block_arr[10], file_arr[10];
printf("\nEnter the Total Number of Blocks:\t");
scanf("%d",&number_of_blocks);
printf("Enter the Total Number of Files:\t");
scanf("%d",&number_of_files); printf("\
nEnter the Size of the Blocks:\n"); for(m =
0; m < number_of_blocks; m++)
{
printf("Block No.[%d]:\t", m + 1);
scanf("%d", &blocks[m]);
}
printf("Enter the Size of the Files:\n");
for(m = 0; m < number_of_files; m++)
{
printf("File No.[%d]:\t", m + 1);
scanf("%d", &files[m]);
}
for(m = 0; m < number_of_files; m++)
{
for(n = 0; n < number_of_blocks; n++)
{
if(block_arr[n] != 1)
{
temp = blocks[n] - files[m];
if(temp >= 0)
{
if(top < temp)
{
file_arr[m] = n;
top = temp;
}
}
}
fragments[m] = top;
block_arr[file_arr[m]] = 1;
top = 0;
}
}
printf("\nFile Number\tFile Size\tBlock Number\tBlock Size\tFragment");
for(m = 0; m < number_of_files; m++)
{
printf("\n%d\t\t%d\t\t%d\t\t%d\t\t%d", m, files[m], file_arr[m], blocks[file_arr[m]],
fragments[m]);
}
printf("\n");
return 0;
}
Practical 10
Program Name: Implement file storage allocation technique: Contiguous(using array), Linked –
list(using linked-list), Indirect allocation (indexing)

Description: A file is a collection of data, usually stored on disk. As a logical entity, a file
enables to divide data into meaningful groups. As a physical entity, a file should be considered in
terms of its organization. The term "file organization" refers to the way in which data is stored in
a file and, consequently, the method(s) by which it can be accessed.

Program: Contiguous (using array)

#include < stdio.h>


#include<conio.h>
void main()
{
int f[50], i, st, len, j, c, k, count = 0;
clrscr();
for(i=0;i<50;i++)
f[i]=0;
printf("Files Allocated are : \n");
x: count=0;
printf(“Enter starting block and length of files: ”);
scanf("%d%d", &st,&len);
for(k=st;k<(st+len);k++)
if(f[k]==0)
count++;
if(len==count)
{
for(j=st;j<(st+len);j++)
if(f[j]==0)
{ f[j]=
1;
printf("%d\t%d\n",j,f[j]);
}
if(j!=(st+len-1))
printf(” The file is allocated to disk\n");
}
else
printf(” The file is not allocated \n");
printf("Do you want to enter more file(Yes - 1/No - 0)");
scanf("%d", &c);
if(c==1)
goto x;
else
exit();
getch();
}

Output:

Files Allocated are :


Enter starting block and length of files: 14 3
14 1
15 1
16 1
The file is allocated to disk
Do you want to enter more file(Yes - 1/No - 0)1
Enter starting block and length of files: 14 1
The file is not allocated
Do you want to enter more file(Yes - 1/No - 0)1
Enter starting block and length of files: 14 4
The file is not allocated
Do you want to enter more file(Yes - 1/No - 0)0

Program:Linked –list (using linked-list)

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
int f[50], p,i, st, len, j, c, k, a;
clrscr();
for(i=0;i<50;i++)
f[i]=0;
printf("Enter how many blocks already allocated: ");
scanf("%d",&p);
printf("Enter blocks already allocated:
"); for(i=0;i<p;i++)
{
scanf("%d",&a);
f[a]=1;
}
x: printf("Enter index starting block and length: ");
scanf("%d%d", &st,&len);
k=len;
if(f[st]==0)
{
for(j=st;j<(st+k);j++)
{
if(f[j]==0)
{ f[j]=
1;
printf("%d------->%d\n",j,f[j]);
}
else
{
printf("%d Block is already allocated \n",j);
k++;
}
}
}
else
printf("%d starting block is already allocated \n",st);
printf("Do you want to enter more file(Yes - 1/No - 0)");
scanf("%d", &c);
if(c==1)
goto x;
else
exit(0);
getch();
}

Output:

Enter how many blocks already allocated: 3

Enter blocks already allocated: 1 3 5

Enter index starting block and length: 2 2

2 >1

3 Block is already allocated

4 >1

Do you want to enter more file(Yes - 1/No - 0)0

Program:Indirect allocation (indexing)

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
int f[50], index[50],i, n, st, len, j, c, k, ind,count=0;
clrscr();
for(i=0;i<50;i++)
f[i]=0;
x:printf("Enter the index block: ");
scanf("%d",&ind);
if(f[ind]!=1)
{
printf("Enter no of blocks needed and no of files for the index %d on the disk : \n", ind);
scanf("%d",&n);
}
else
{
printf("%d index is already allocated \n",ind);
goto x;
}
y: count=0;
for(i=0;i<n;i++)
{
scanf("%d", &index[i]);
if(f[index[i]]==0)
count++;
}
if(count==n)
{
for(j=0;j<n;j++)
f[index[j]]=1;
printf("Allocated\n");
printf("File Indexed\n");
for(k=0;k<n;k++)
printf("%d------->%d : %d\n",ind,index[k],f[index[k]]);
}
else
{
printf("File in the index is already allocated \n");
printf("Enter another file indexed");
goto y;
}
printf("Do you want to enter more file(Yes - 1/No - 0)");
scanf("%d", &c);
if(c==1)
goto x;
else
exit(0);
getch();
}

Output:

Enter the index block: 5


Enter no of blocks needed and no of files for the index 5 on the disk :
4
1234
Allocated
File Indexed
5------->1 : 1
5-------->2 : 1
5-------->3 : 1
5-------->4 : 1
Do you want to enter more file(Yes - 1/No - 0)1
Enter the index block: 4
4 index is already allocated
Enter the index block: 6
Enter no of blocks needed and no of files for the index 6 on the disk :
2
78
A5llocated
File Indexed
6------->7 : 1
6-------->8 : 1
Do you want to enter more file(Yes - 1/No - 0)0

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy