Operating System Lab Manual
Operating System Lab Manual
LAB MANUAL
Operating System
(CS-405)
NAME:
ENROLLMENT NUMBER:
SESSION: 2019-20
.
10 Write a program to implement & Compare various Disk & Drum
scheduling Algorithms
Introduction
An Operating system is software that creates a relation between the User, Software and
Hardware. It is an interface between the all. All the computers need basic software known as an
Operating System (OS) to function.
The OS acts as an interface between the User, Application Programs, Hardware and the
System Peripherals. The OS is the first software to be loaded when a computers starts up. The
entire application programs are loaded after the OS.
A single-tasking system can only run one program at a time, while a multi-tasking
operating system allows more than one program to be running in concurrency. This is achieved by
time-sharing, dividing the available processor time between multiple processes that are each
interrupted repeatedly in time slices by a task-scheduling subsystem of the operating system.
Process Scheduling
Processes are the Small Programs those are executed by the user
according to their Request. CPU Executes all the Process according to Some
Rules or Some Schedule. Scheduling ist hat in which each process have Some
Amount of Time of CPU. Scheduling Provides Time of CPU to the Each Process.
The First Come First Served (FCFS) Scheduling Algorithm is the simplest one. In this
algorithm the set of ready processes is managed as FIFO (first-in-first-out) Queue. The processes
are serviced by the CPU until completion in order of their entering in the FIFO queue.
A process once allocated the CPU keeps it until releasing the CPU either by terminating or
requesting I/O. For example, interrupted process is allowed to continujre running after interrupt
handling is done with.
9
AIM: To write the program to implement CPU & scheduling algorithm for first come first serve scheduling.
ALGORITHM:
PROGRAM :
#include<stdio.h>
struct process
{
int main()
{
int i,n,totwt,tottt,avg1,avg2; clrscr();
}
p[1].wt=0; p[1].tt=p[1].bt+p[1].wt; i=2;
while(i<=n)
{
i=1;
p[i].wt=p[i-1].bt+p[i-1].wt; p[i].tt=p[i].bt+p[i].wt; i ++;
10
11
}
totwt = tottt = 0;
OUTPUT:
Process sid bt wt tt
1 2 0 2
2 4 2 6
3 6 6 12
avg1=2 avg2=6
RESULT: Thus the FIFO process scheduling program was executed and verified successfully.
12
13
SHORTET JOB FIRST SCHEDULING
14
Practical No. 2
Aim: To write a program to implement cpu scheduling algorithm for shortest job first
scheduling.
ALGORITHM:
1. Start the program. Get the number of processes and their burst time.
2. Initialize the waiting time for process 1 as 0.
3. The processes are stored according to their burst time.
4. The waiting time for the processes are calculated a follows:
for(i=2;i<=n;i++).wt.p[i]=p[i=1]+bt.p[i-1].
5. The waiting time of all the processes summed and then the average time is calculate
6. The waiting time of each processes and average time are displayed.
7. Stop the program.
PROGRAM:
#include<stdio.h>
#include<conio.h>
struct process
for(i=1;i<=n;i++)
15
{
p[i].pid=i;
for(i=1;i<n;i++){ for(j=i+1;j<=n;j++)
if(p[i].bt>p[j].bt)
temp.pid=p[i].pid;
p[i].pid=p[j].pid; p[j].pid=temp.pid;
temp.bt=p[i].bt;p[i].bt=p[j].bt; p[j].bt=temp.bt;
while(i<=n){
p[i].wt=p[i-1].bt+p[i-1].wt;
p[i].tt=p[i].bt+p[i].wt; i++;
16
i=1;
totwt=tottt=0;
tottt=p[i].tt+tottt; i++;
} avg1=totwt/n; avg2=tottt/n;
return 0; }
OUTPUT:
processid bt wt tt
1 2 0 2
2 4 2 6
3 6 6 12
AVG1=2.000000 AVG2=6.000000
Practical No 3
Aim: To write a ‘C’ program to perform priority scheduling.
ALGORITHM:
PROGRAM:
#include<stdio.h>
#include<conio.h>
struct process
{
int pid; int bt; int wt; int tt; int prior;
}
p[10],temp; int main()
{
int i,j,n,totwt,tottt,arg1,arg2; clrscr();
printf("enter the number of process"); scanf("%d",&n);
for(i=1;i<=n;i++)
{
p[i].pid=i;
printf("enter the burst time"); scanf("%d",&p[i].bt); printf("\n enter the priority");
scanf("%d",&p[i].prior);
}
for(i=1;i<n;i++)
{
for(j=i+1;j<=n;j++)
{
if(p[i].prior>p[j].prior)
temp.pid=p[i].pid; p[i].pid=p[j].pid;
p[j].pid=temp.pid; temp.bt=p[i].bt;
p[i].bt=p[j].bt;
p[j].bt=temp.bt; temp.prior=p[i].prior; p[i].prior=p[j].prior; p[j].prior=temp.prior;
}
}
}
p[i].wt=0;
p[1].tt=p[1].bt+p[1].wt; i=2;
while(i<=n)
{
50
p[i].wt=p[i-1].bt+p[i-1].wt;
p[i].tt=p[i].bt+p[i].wt; i++;
}
i=1;
totwt=tottt=0;
printf("\n process to \t bt \t wt \t tt"); while(i<=n)
{
printf("\n%d\t %d\t %d\t %d\t",p[i].pid,p[i].bt,p[i].wt,p[i].tt); totwt=p[i].wt+totwt;
tottt=p[i].tt+tottt;
i++;
}
arg1=totwt/n; arg2=tottt/n;
printf("\n arg1=%d \t arg2=%d\t",arg1,arg2);
getch();
return 0;
}
OUTPUT:
2 6 4 10 14
3 2 10 12 22
avg1=4 avg2=8
51
Practical No. 4
Aim: To write a program to implement CPU scheduling for Round Robin Scheduling.
ALGORITHM:
1. Get the number of process and their burst time.
2. Initialize the array for Round Robin circular queue as ‘0’.
3. The burst time of each process is divided and the quotients are stored on the round Robin
array.
4. According to the array value the waiting time for each process and the average time are
calculated as line the other scheduling.
5. The waiting time for each process and average times are displayed.
6. Stop the program.
PROGRAM :
#include<stdio.h>
#include<conio.h>
struct process
{
int pid,bt,tt,wt;
};
int main()
{
struct process x[10],p[30];
int i,j,k,tot=0,m,n;
float wttime=0.0,tottime=0.0,a1,a2;
clrscr();
printf("\nEnter the number of process:\t"); scanf("%d",&n);
for(i=1;i<=n;i++){ x[i].pid=i;
printf("\nEnter the Burst Time:\t"); scanf("%d",&x[i].bt); tot=tot+x[i].bt;
}
printf("\nTotal Burst Time:\t%d",tot); p[0].tt=0;
k=1;
printf("\nEnter the Time Slice:\t"); scanf("%d",&m);
for(j=1;j<=tot;j++)
{
for(i=1;i<=n;i++)
{
if(x[i].bt !=0)
{
p[k].pid=i; if(x[i].bt-m<0)
{
p[k].wt=p[k-1].tt;
p[k].bt=x[i].bt; p[k].tt=p[k].wt+x[i].bt;
x[i].bt=0; k++;
}
else
52
{
p[k].wt=p[k-1].tt;
p[k].tt=p[k].wt+m;
x[i].bt=x[i].bt-m; k++;
}}}}
OUTPUT:
process id wt tt
1 0 2
2 2 4
3 4 6
1 6 7
process id wt tt
2 7 9
3 9 11
2 11 12
53
3 12 14
3 14 15
RESULT:
Thus the Round Robin scheduling program was executed and verified successfully.
54
Practical No. 6
ALGORITHM:
1. Declare variable for producer & consumer as pthread-t-tid produce tid consume.
2. Declare a structure to add items, semaphore variable set as struct.
3. Read number the items to be produced and consumed.
4. Declare and define semaphore function for creation and destroy.
5. Define producer function.
6. Define consumer function.
7. Call producer and consumer.
8. Stop the execution.
PROGRAM:
#include<stdio.h>
void main()
{
bufsize = 10;
while(choice !=3)
case 1: if((in+1)%bufsize==out)
printf("\nBuffer is Full");
else
55
printf("\nEnter the value: ");
scanf("%d", &produce); buffer[in] =
produce;
in = (in+1)%bufsize;
break;
consume = buffer[out];
break;
} } }
OUTPUT:
Buffer is Empty
56
RESULT:
Thus the producer consumer program was executed and verified successfully
Practical No. 7
Aim : Write a program to implement classical inter process communication problem (Reader
Writers).
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void readfile();
void writefile();
int a,b,i=0;
char c[40];
char buffer[89];
char *g;
FILE *fr,*fw;
void main()
{
clrscr();
x:
printf("\n1.Read \n2.Write");
printf("\nUSER A enter your choice");
scanf("%d",&a);
printf("\nUSER B enter your choice");
scanf("%d",&b);
getch();
if(a==1&&b==1)
{
readfile();
}
else if(a==1&&b==2)
{writefile();
readfile();
}
else if(a==2&&b==1)
{
readfile();
writefile();
}
else if(a==2&&b==2);
{
57
printf("both users are not allowed to write");
return;
}
}
void readfile()
{
fr=fopen("filename.c","r");
printf("\n file content is:");
while(!feof(fr) )
{
c[i]=(char)fgetc(fr);
printf("%c",c[i]);
i++;
}
fclose (fr);
}
void writefile()
{
printf("enter your content to write:\n");
buffer[0]=100;
g=cgets(buffer);
fw=fopen("filename.c","w");
fwrite(g,strlen(g),1,fw);
fclose(fw);
}
Output:
Enter your choice 1.Read 2.Write
user a enter your choice 2
user b aenter your choice 1
file content is :i am a student .enter your content to write:
i am a student of GGITS//
58
Practical No 9
Aim: Write a program to implement classical inter process communication problem (Dining
Philosophers).
PROGRAM:
#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#define N 5
#define THINKING 0
#define HUNGRY 1
#define EATING 2
#define LEFT (ph_num+4)%N
#define RIGHT (ph_num+1)%N
sem_t mutex;
sem_t S[N];
void * philospher(void *num);
void take_fork(int);
void put_fork(int);
void test(int);
int state[N];
int phil_num[N]={0,1,2,3,4};
int main()
{
int i;
pthread_t thread_id[N];
sem_init(&mutex,0,1);
for(i=0;i<N;i++)
sem_init(&S[i],0,0);
for(i=0;i<N;i++)
{
pthread_create(&thread_id[i],NULL,philospher,&phil_num[i]);
printf("Philosopher %d is thinking\n",i+1);
}
for(i=0;i<N;i++)
pthread_join(thread_id[i],NULL);
}
void *philospher(void *num)
{
while(1)
{
int *i = num;
sleep(1);
59
take_fork(*i);
sleep(0);
put_fork(*i);
}
}
void take_fork(int ph_num)
{
sem_wait(&mutex);
state[ph_num] = HUNGRY;
printf("Philosopher %d is Hungry\n",ph_num+1);
test(ph_num);
sem_post(&mutex);
sem_wait(&S[ph_num]);
sleep(1);
}
void test(int ph_num)
{
if (state[ph_num] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING)
{
state[ph_num] = EATING;
sleep(2);
printf("Philosopher %d takes fork %d and %d\n",ph_num+1,LEFT+1,ph_num+1);
printf("Philosopher %d is Eating\n",ph_num+1);
sem_post(&S[ph_num]);
}}
void put_fork(int ph_num)
{
sem_wait(&mutex);
state[ph_num] = THINKING;
printf("Philosopher %d putting fork %d and %d down\n",ph_num+1,LEFT+1,ph_num+1);
printf("Philosopher %d is thinking\n",ph_num+1);
test(LEFT);
test(RIGHT);
sem_post(&mutex);
}
OUTPUT:
Philosopher 1 is thinking
Philosopher 2 is thinking
Philosopher 3 is thinking
Philosopher 4 is thinking
Philosopher 5 is thinking
Philosopher 1 is Hungry
Philosopher 1 takes fork 5 and 1
Philosopher 1 is Eating
Philosopher 2 is Hungry
Philosopher 3 is Hungry
Philosopher 3 takes fork 2 and 3
Philosopher 3 is Eating
Philosopher 4 is Hungry
Philosopher 5 is Hungry
Philosopher 1 putting fork 5 and 1 down
Philosopher 1 is thinking
60
Philosopher 5 takes fork 4 and 5
Philosopher 5 is Eating
Philosopher 3 putting fork 2 and 3 down
Philosopher 3 is thinking
Practical No.10
Aim: Write a program to implement & Compare various page replacement algorithms.
ALGORITHM:
61
Aim: Simulate LRU page replacement algorithms
ALGORITHM:
1. Start
2. Read the number of frames
3. Read the number of pages
4. Read the page numbers
5. Initialize the values in frames to -1
6. Allocate the pages in to frames by selecting the page that has not been used for the longest period of
time.
7. Display the number of page faults.
8. stop
ALGORITHM:
6. Allocate the pages in to frames by selecting the page that will not be used for the longest period
of time.
62
PROGRAM:
#include<stdio.h>
int n,pg[30],fr[10];
void fifo();
void optimal();
void lru();
void main()
int i,ch;
scanf(“%d”,&n);
printf(“\nEnter sequence:”);
scanf(“%d”,&pg[i]);
do
printf(“\n\tMENU\n”);
printf(“\n1)FIFO”);
printf(“\n2)OPTIMAL”);
printf(“\n3)LRU”);
printf(“\n4)Exit”);
scanf(“%d”,&ch);
switch(ch)
63
case 1: fifo();
break;
case 2: optimal();
break;
case 3: lru();
break;
}while(ch!=4);
getchar();
void fifo()
int i,f,r,s,count,flag,num,psize;
f=0;
r=0;
s=0;
flag=0;
count=0;
scanf(“%d”,&psize);
for(i=0;i<psize;i++)
fr[i]=-1;
64
}
while(s<n)
flag=0;
num=pg[s];
for(i=0;i<psize;i++)
if(num==fr[i])
s++;
flag=1;
break;
if(flag==0)
if(r<psize)
fr[r]=pg[s];
r++;
s++;
count++;
else
if(f<psize)
65
fr[f]=pg[s];
s++;
f++;
count++;
else
f=0;
printf(“\n”);
for(i=0;i<psize;i++)
printf(“%d\t”,fr[i]);
printf(“\nPage Faults=%d”,count);
getchar();
void optimal()
int count[10],i,j,k,fault,f,flag,temp,current,c,dist,max,m,cnt,p,x;
fault=0;
dist=0;
k=0;
scanf(“%d”,&f);
66
for(i=0;i<f;i++)
count[i]=0;
fr[i]=-1;
for(i=0;i<n;i++)
flag=0;
temp=pg[i];
for(j=0;j<f;j++)
if(temp==fr[j])
flag=1;
break;
if((flag==0)&&(k<f))
fault++;
fr[k]=temp;
k++;
else if((flag==0)&&(k==f))
fault++;
for(cnt=0;cnt<f;cnt++)
67
{
current=fr[cnt];
for(c=i;c<n;c++)
if(current!=pg[c])
count[cnt]++;
else
break;
max=0;
for(m=0;m<f;m++)
if(count[m]>max)
max=count[m];
p=m;
fr[p]=temp;
printf(“\n”);
for(x=0;x<f;x++)
printf(“%d\t”,fr[x]);
68
printf(“\nTotal number of faults=%d”,fault);
getchar();
void lru()
int count[10],i,j,k,fault,f,flag,temp,current,c,dist,max,m,cnt,p,x;
fault=0;
dist=0;
k=0;
scanf(“%d”,&f);
for(i=0;i<f;i++)
count[i]=0;
fr[i]=-1;
for(i=0;i<n;i++)
flag=0;
temp=pg[i];
for(j=0;j<f;j++)
if(temp==fr[j])
flag=1;
69
break;
if((flag==0)&&(k<f))
fault++;
fr[k]=temp;
k++;
else if((flag==0)&&(k==f))
fault++;
for(cnt=0;cnt<f;cnt++)
current=fr[cnt];
for(c=i;c>0;c–)
if(current!=pg[c])
count[cnt]++;
else
break;
max=0;
for(m=0;m<f;m++)
if(count[m]>max)
70
{
max=count[m];
p=m;
fr[p]=temp;
printf(“\n”);
for(x=0;x<f;x++)
printf(“%d\t”,fr[x]);
getchar();
OUTPUT
1)FIFO
2)OPTIMAL
3)LRU
4)Exit
0 -1 -1
0 1 -1
71
0 1 2
3 1 2
3 0 2
3 0 1
3 0 1
2 0 1
2 3 1
2 3 0
2 3 0
1 3 0
1 2 0
1 2 3
1 2 3
4 2 3
4 5 3
4 5 6
4 5 6
7 5 6
Page Faults=16
MENU
1)FIFO
2)OPTIMAL
3)LRU
4)Exit
0 -1 -1
72
0 1 -1
0 1 2
0 1 3
0 1 3
0 1 3
0 2 3
0 2 3
0 2 3
1 2 3
1 2 3
1 2 3
4 2 3
5 2 3
6 2 3
7 2 3
1)FIFO
2)OPTIMAL
3)LRU
4)Exit
0 -1 -1
0 1 -1
0 1 2
3 1 2
73
3 0 2
1 0 2
1 0 2
1 3 2
0 3 2
1 3 2
1 3 2
1 3 2
4 3 2
4 3 5
6 3 5
6 7 5
74
Practical No.11
Aim: Write a program to implement & Compare various Disk & Drum scheduling Algorithms
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
//#include<time.h>
int request[100],st,cylinders,n;
//time_t t;
void random(void )
75
for(int i=0;i<n;i++)
//srand(request[(rand()%n)]);
request[i]=rand()%cylinders+1;
void display(void )
for(int i=0;i<n;i++)
int main()
int choice;
void fcfs(void );
void scan(void );
cin>>cylinders>>st;
cout<<"\npress 0 to generate random disk requests and any other no. to give your own requests : ";
76
cin>>choice;
if(choice==0)
cin>>n;
random();
else
while(1)
cin>>request[n++];
if(request[n-1]==0||n==100)
n--;
break;
cin>>choice;
switch(choice)
77
case 0:
fcfs();
break;
case 1:
scan();
break;
default:
break;
getch();
return 0;
void fcfs(void )
display();
for(i=0;i<n;i++)
cout<<"-->"<<request[i];
total=total+abs(request[i]-st);
st=request[i];
78
void scan(void )
int total=0,i,j,temp;
display();
for(i=0;i<n;i++)
for(j=0;j<n-1-i;j++)
if(request[j]>request[j+1])
temp=request[j];
request[j]=request[j+1];
request[j+1]=temp;
display();
if(st<request[0])
for(i=0;i<n;i++)
cout<<"-->"<<request[i];
total+=abs(request[i]-st);
st=request[i];
79
}
else
i=0;
temp=0;
while(st>request[i++])
temp++;
for(i=temp;i<n;i++)
cout<<"-->"<<request[i];
total+=abs(request[i]-st);
st=request[i];
if(i==n-1)
total=total+2*cylinders-request[i];
st=0;
i=0;
n=temp;
if(st!=cylinders)
cout<<"-->"<<cylinders;
cout<<"-->"<<1;
80
}
Practical No.12
81
resources.
3. Attacking preemption: not something you want to do.
4. Attacking hold and wait condition: make a process hold at the most 1 resource
5. At a time. Make all the requests at the beginning. Nothing policy. If you feel, retry.
6. Attacking circular wait: Order all the resources. Make sure that the requests are issued in the
7. Correct order so that there are no cycles present in the resource graph. Resources
numbered 1 ... n.
8. Resources can be requested only in increasing
9. Order. i.e. you cannot request a resource whose no is less than any you may be holding.
10. Stop the program
82
PROGRAM: (SIMULATE ALGORITHM FOR DEADLOCK PREVENTION)
#include<stdio.h>
#include<conio.h>
clrscr( );
matrix"); for(i=0;i<p;i++)
for(j=0;j<r;j++)
scanf("%d",&alloc[i][j]);
scanf("%d",&max[i][j]); printf("enter
scanf("%d",&avail[i]); for(i=0;i<p;i+
+) for(j=0;j<r;j++) need[i][j]=max[i][j]-
if(flag==0)
if(finish[i]!=1)
for(j=0;j<r;j++)
Gyan Ganga Institute of Technology and Sciences, Jabalpur
if(avail[j]<need[i][j])
avail[j]=need[i][j];
}fun();
if(avail[j]<need[i][j])
avail[j]=need[i][j];
alloc[i][j]=0;
fun( );
printf("\n\n daed lock is prevented by allocating needed resources"); printf(" \n \n failing:Hold and
for(j=0;j<r;j++)
if(avail[j]<need[i][j])
avail[j]=need[i][j];
fun( );
getch( );
return 0;
Gyan Ganga Institute of Technology and Sciences, Jabalpur
fun()
while(1)
for(flag=0,i=0;i<p;i++)
if(finish[i]==0)
for(j=0;j<r;j++)
if(need[i][j]<=avail
[j]) continue;
else break;
if(j==r)
for(j=0;j<r;j++) avail[j]+=alloc[i][j];
flag=1;
finish[i]=1;
}}
if(flag==0) break;
}return 0;
Gyan Ganga Institute of Technology and Sciences, Jabalpur
OUTPUT:
matrix 2 4 5
345
561
Enter available
matrix2 Failing:
Mutual
Exclusion
Practical No.13
long * bindate_1() {
static long timeval; /* must be static */
timeval = time((long *) 0);
return (&timeval);
}
****************************************************
Commands:
rpcgen date.x
gcc -c date_clnt.c
gcc -c date_svc.c
gcc -c dateproc.c
gcc -c rdate.c
gcc -o client date_clnt.o rdate.o
gcc -o server date_svc.o dateproc.o
Gyan Ganga Institute of Technology and Sciences, Jabalpur
Practical No.14
The purpose of a device driver is to handle requests made by the kernel with regard to a
particular type of device. There is a well-defined and consistent interface for the kernel to make
these requests. By isolating device-specific code in device drivers and by having a consistent
interface to the kernel, adding a new device is easier
A device driver is a software module that resides within the Digital UNIX kernel and is the
software interface to a hardware device or devices. A hardware device is a peripheral, such as a
disk controller, tape controller, or network controller device. In general, there is one device
driver for each type of hardware device. Device drivers can be classified as:
A block device driver is a driver that performs I/O by using file system block-sized buffers from
a buffer cache supplied by the kernel. The kernel also provides for the device driver support
interfaces that copy data between the buffer cache and the address space of a process.
Block device drivers are particularly well-suited for disk drives, the most common block devices.
For block devices, all I/O occurs through the buffer cache.
Gyan Ganga Institute of Technology and Sciences, Jabalpur
A character device driver does not handle I/O through the buffer cache, so it is not tied to a
single approach for handling I/O. You can use a character device driver for a device such as a
line printer that handles one character at a time. However, character drivers are not limited to
performing I/O one character at a time (despite the name ``character'' driver). For example, tape
drivers frequently perform I/O in 10K chunks. You can also use a character device driver when it
is necessary to copy data directly to or from a user process.
Because of their flexibility in handling I/O, many drivers are character drivers. Line printers,
interactive terminals, and graphics displays are examples of devices that require character device
drivers.
A terminal device driver is actually a character device driver that handles I/O character
processing for a variety of terminal devices. Like any character device, a terminal device can
accept or supply a stream of data based on a request from a user process. It cannot be mounted as
a file system and, therefore, does not use data caching.
A network device driver attaches a network subsystem to a network interface, prepares the
network interface for operation, and governs the transmission and reception of network frames
over the network interface. This book does not discuss network device drivers.
Not all device drivers control physical hardware. Such device drivers are called ``pseudodevice''
drivers. Like block and character device drivers, pseudodevice drivers make use of the device
driver interfaces. Unlike block and character device drivers, pseudodevice drivers do not operate
on a bus. One example of a pseudodevice driver is the pseudoterminal or pty terminal driver,
which simulates a terminal device. The pty terminal driver is a character device driver typically
used for remote logins.
Digital UNIX provides the tools and techniques for you to produce a single binary module. A
single binary module is the executable image of a device driver that can be statically or
dynamically configured into the kernel. A single binary module has a file extension of .mod. The
.mod file for the current version of Digital UNIX is not the same as the .mod file used in
previous versions of the operating system.
Gyan Ganga Institute of Technology and Sciences, Jabalpur
Auto configuration
The kernel calls a device driver (specifically, the driver's probe interface) at auto
configuration time to determine what devices are available and to initialize them.
I/O operations
The kernel calls a device driver to perform I/O operations on the device. These operations
include opening the device to perform reads and writes and closing the device.
Interrupt handling
The kernel calls a device driver to handle interrupts from devices capable of generating
them.
Special requests
The kernel calls a device driver to handle special requests through ioctl calls.
Re-initialization
The kernel calls a device driver to reinitialize the driver, the device, or both when the bus
(the path from the CPU to the device) is reset.
The kernel calls a device driver (specifically, the driver's configure interface) to handle
requests that result from use of the sysconfig utility. The sysconfig utility allows a system
manager to dynamically configure, unconfigure, query, and reconfigure a device. These
requests cause the kernel to call the device driver's configure interface. In addition, the
driver's configure interface performs one-time initializations when called by the boot
software or by the sysconfig utility.