Unit 2 Studocu
Unit 2 Studocu
OS - Unit II - Unit 2
PROCESS:
Process State:
As a process executes, it changes state. The state of a process is defined in part by the current
activity of that process. A process may be in one of the following states:
A new process is initially put in the ready queue. It waits there until it is selected for execution, or
dispatched.
Once the process is allocated the CPU and is executing, one of several events could occur:
• The process could issue an I/O request and then be placed in an I/O queue.
• The process could create a new child process and wait for the child’s termination.
• The process could be removed forcibly from the CPU, as a result of an interrupt, and be put back in
the ready queue.
Schedulers:
The operating system must select, for scheduling purposes, processes from the queues in some
approach. The selection process is carried out by the appropriate scheduler.
It makes use of two types of schedulers
o Long term scheduler or job scheduler
o Short term scheduler or CPU scheduler.
o Medium term scheduler
The long-term scheduler, or job scheduler, selects processes from the job queue and loads them
into memory for execution.
The short-term scheduler, or CPU scheduler, selects from among the processes that are ready
to execute and allocates the CPU to one of them.
The Long term scheduler must have a careful selection of both I/O Bound and CPU Bound
process.
An I/O-bound process is one that spends more of its time doing I/O than it spends doing
computations.
A CPU-bound process, in contrast, generates I/O requests infrequently, using more of its time
doing computations.
If all processes are I/O bound, the ready queue will almost always be empty, If all processes are
CPU bound, the I/O waiting queue will almost always be empty, devices will go unused.
The medium-term scheduler is used to remove a process from memory to reduce the degree of
multiprogramming. Later, the process can be reintroduced into memory, and its execution can be
continued where it left off. This scheme is called swapping.
The process is swapped out, and is later swapped in, by the medium-term scheduler.
Context Switch:
The process of switching the CPU from one process to another process requires performing a
state save of the current process and a state restore of a different process. This task is known as a
context switch.
When an interrupt occurs, the system needs to save the current context of the process running on
the CPU so that it can restore that context when its processing is done.
The context is represented in the PCB of the process. It includes the value of the CPU registers,
the process state and memory management information.
OPERATIONS ON PROCESSES:
The operating system must provide a mechanism for process creation and termination. The
process can be created and deleted dynamically by the operating system.
The Operations on the process includes
Process creation
Process Termination
Process Creation:
The init process serves as the root parent process for all the user process.
Once the system has booted, the init process can also create various user processes, such as a web
or print server, an ssh server.
The kthreadd process is responsible for creating additional processes that perform tasks on behalf
of the kernel
The sshd process is responsible for managing clients that connect to the system by using
ssh(Secure shell)
The login process is responsible for managing clients that directly log onto the system
The command ps –el will list complete information for all processes currently active in the
system.
When a process creates a new process, two possibilities for execution exist:
1. The parent continues to execute concurrently with its children.
2. The parent waits until some or all of its children have terminated
There are also two address-space possibilities for the new process:
1. The child process is a duplicate of the parent process (it has the same program as the parent).
2. The child process has a new program loaded into it.
A new process is created by the fork() system call. The new process consists of a copy of the
address space of the original process. This mechanism allows the parent process to communicate
easily with its child process.
The return code for the fork() is zero for the new (child) process, whereas the (nonzero)
process identifier of the child is returned to the parent.
After a fork() system call, one of the two processes typically uses the exec() system call to
replace the process’s memory space with a new program.
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
Pid_t pid;
/* fork a child process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (pid == 0) { /* child process */
execlp("/bin/ls","ls",NULL);
}
else { /* parent process */
/* parent will wait for the child to complete */
wait(NULL);
printf("Child Complete");
}
return 0;
}
Process Termination:
A process terminates when it finishes executing its final statement and asks the operating system
to delete it by using the exit() system call.
At that point, the process may return a status value (typically an integer) to its parent process.
All the resources of the process—including physical and virtual memory, open files, and I/O
buffers—are deallocated by the operating system
A parent may terminate the execution of one of its children for a variety of reasons, such as
• The child has exceeded its usage of some of the resources that it has been allocated.
• The task assigned to the child is no longer required.
• The parent is exiting, and the operating system does not allow a child to continue if its parent
terminates.
Some systems do not allow a child to exist if its parent has terminated. In such systems, if a
process terminates (either normally or abnormally), then all its children must also be terminated.
This phenomenon is referred to as cascading termination.
A parent process may wait for the termination of a child process by using the wait() system call
This system call also returns the process identifier of the terminated child so that the parent can
tell which of its children has terminated:
pid t pid;
int status;
pid = wait(&status);
A process that has terminated, but whose parent has not yet called wait(), is known as a zombie
process.
INTERPROCESS COMMUNICATION:
A process can be either an independent process or a cooperating process.
A process is independent if it cannot affect or be affected by the other processes executing in the
system. Any process that does not share data with any other process is independent.
A process is cooperating if it can affect or be affected by the other processes executing in the
system. Clearly, any process that shares data with other processes is a cooperating process.
Advantages of cooperating process
i) Information sharing
ii) Computation speedup
iii) Modularity
iv) Convenience.
Shared-Memory Systems:
Interprocess communication using shared memory requires communicating processes to establish
a region of shared memory.
Shared-memory region resides in the address space of the process creating the shared-memory
segment.
Other processes that wish to communicate using this shared-memory segment must attach it to
their address space.
They can then exchange information by reading and writing data in the shared areas.
EXAMPLE:PRODUCER – CONSUMER PROCESS:
A producer process produces information that is consumed by a consumer process.
One solution to the producer–consumer problem uses shared memory
To allow producer and consumer processes to run concurrently, we must have available a buffer
of items that can be filled by the producer and emptied by the consumer.
This buffer will reside in a region of memory that is shared by the producer and consumer
processes. A producer can produce one item while the consumer is consuming another item.
Two types of buffers can be used.
o Bounded Buffer.
o Unbounded Buffer.
The unbounded buffer places no practical limit on the size of the buffer. The consumer may
have to wait for new items, but the producer can always produce new items.
The bounded buffer assumes a fixed buffer size. In this case, the consumer must wait if the
buffer is empty, and the producer must wait if the buffer is full.
The following variables reside in a region of memory shared by the producer and consumer
processes:
#define BUFFER SIZE 10
typedef struct {
...
}item;
item buffer[BUFFER SIZE];
int in = 0;
int out = 0;
The variable in points to the next free position in the buffer; out points to the first full position in
the buffer. The buffer is empty when in == out; the buffer is full when ((in + 1) % BUFFER SIZE)
== out.
CODE FOR PRODUCER PROCESS:
item next produced;
while (true) {
/* produce an item in next produced */
while (((in + 1) % BUFFER SIZE) == out)
; /* do nothing */
buffer[in] = next produced;
in = (in + 1) % BUFFER SIZE;
}
The producer process has local variable next produced in which the new item to be produced is
stored.
The consumer process has a local variable next consumed in which the item to be consumed is
stored.
This scheme allows at most BUFFER SIZE − 1 items in the buffer at the same time.
CODE FOR CONSUMER PROCESS
item next consumed;
while (true) {
while (in == out)
; /* do nothing */
next consumed = buffer[out];
out = (out + 1) % BUFFER SIZE;
/* consume the item in next consumed */
}
Message-Passing Systems:
Message passing provides a mechanism to allow processes to communicate and to synchronize
their actions without sharing the same address space
A message-passing facility provides at least two operations:
o Send(message)
o Receive(message)
If processes P and want to communicate, they must send messages to and receive messages from
each other: a communication link must exist between them.
There are several methods for logically implementing a link and the send()/receive() operations:
o Direct or indirect communication
o Synchronous or asynchronous communication
o Automatic or explicit buffering
10
Communication between processes takes place through calls to send() and receive() primitives.
Message passing may be either blocking or nonblocking— also known as synchronous and
asynchronous
Blocking send. The sending process is blocked until the message is received by the receiving
process or by the mailbox
Nonblocking send. The sending process sends the message and resumes Operation
Blocking receive. The receiver blocks until a message is available.
Nonblocking receive. The receiver retrieves either a valid message or a null.
When both send() and receive() are blocking, we have a rendezvous between the sender and the
receiver.
Automatic or explicit buffering:
Messages exchanged by communicating processes reside in a temporary queue. Basically, such
queues can be implemented in three ways:
o Zero capacity.
o Bounded capacity
o unbounded capacity
Zero capacity. The queue has a maximum length of zero In this case, the sender must block until
the recipient receives the message.
Bounded capacity. The queue has finite length n; thus, at most n messages can reside in it.
11
Unbounded capacity. The queue’s length is potentially infinite; thus, any number of messages
can wait in it. The sender never blocks.
THREADS-OVERVIEW:
A thread is a basic unit of CPU utilization. It is a smallest unit of execution of a program that
determines the flow of control of execution.
It comprises a thread ID, a program counter, a register set, and a stack.
It shares with other threads belonging to the same process its code section, data section, and other
operating-system resources, such as open files.
Within a process, there may be one or more threads, each with the following:
o A thread execution state (Running, Ready, etc.).
o A saved thread context when not running; one way to view a thread is as an independent
program counter operating within a process.
o An execution stack
o Access to the memory and resources of its process,
A process with a single flow of control is called as heavy weighted process.
ADVANTAGES OF MULTITHREADING:
Responsiveness: Multithreading an interactive application may allow
a program to continue running even if part of it is blocked.
Resource sharing: threads share the memory and the resources of the process to
which they belong by default.
12
Economy of scale: Because threads share the resources of the process to which they
belong, it is more economical to create and context-switch threads.
Effective multiprocessor utilization: The benefits of multithreading can be even
greater in a multiprocessor architecture
MULTICORE PROGRAMMING:
The process of placing multiple computing cores on a single chip is called as multicore
programming.
Each core appears as a separate processor to the operating system, whether the cores appear
across CPU chips or within CPU chips.
Multithreaded programming provides a mechanism for more efficient use of these multiple
computing cores and improved concurrency
On a system with a single computing core, concurrency merely means that the execution of the
threads will be interleaved over time because the processing core is capable of executing only one
thread at a time.
On a system with multiple cores, however, concurrency means that the threads can run in parallel,
because the system can assign a separate thread to each core
A system is parallel if it can perform more than one task simultaneously.
A concurrent system supports more than one task by allowing all the tasks to make progress.
Thus, it is possible to have concurrency without parallelism.
There are two types of parallelism
o Data Parallelism
o Task parallelism.
Data parallelism :
This focuses on distributing subsets of the same data across multiple computing cores and
performing the same operation on each core.
Task parallelism:
This involves distributing not data but tasks (threads) across multiple computing cores. Each
thread is performing a unique operation. Different threads may be operating on the same data, or
they may be operating on different data.
Thus data parallelism involves the distribution of data across multiple cores and task parallelism
on the distribution of tasks across multiple cores.
13
Combined approach:
Some operating systems provide a combined ULT/KLT facility
14
15
The many-to-many model (Figure 4.7) multiplexes many user-level threads to a smaller or equal
number of kernel threads.
The number of kernel threads may be specific to either a particular application or a particular
machine developers can create as many user threads as necessary, and the corresponding kernel
threads can run in parallel on a multiprocessor.
Each process is assigned a security access token, called the primary token of the process
When a user first logs on,
Windows creates an access token that includes the security ID for the user.
Every process that is created by or runs on behalf of this user has a copy of this access token.
Windows uses the token to validate the user’s ability to access secured objects or to perform
restricted functions on the system
Process contains a series of blocks that define the virtual address space currently assigned to this
process.
16
The process includes an object table, with handles to other objects such as threads, files and data
known to this process.
Process and Thread Objects:
Windows makes use of two types of process-related objects:
i) processes
ii) Threads
A process is an entity corresponding to a user job or application that owns resources, such as
memory, and opens files.
A thread is a dispatchable unit of work that executes sequentially and is interruptible, so that the
processor can turn to another thread.
Each process is defined by a number of attributes and encapsulates a number of actions, or
services, that it may perform.
Each thread is defined by a number of attributes and encapsulates a number of actions, or services,
that it may perform.
17
A Windows process must contain at least one thread to execute. That thread may then create other
threads.
In a multiprocessor system, multiple threads from the same process may execute in parallel
An attribute called thread processor affinity is the set of processors in a multiprocessor system
that may execute this thread; this set is equal to or a subset of the process processor affinity.
Multithreading:
Windows supports concurrency among processes because threads in different processes may
execute concurrently.
Multiple threads within the same process may be allocated to separate processors and execute
simultaneously.
Threads within the same process can exchange information through their common address space
and have access to the shared resources of the process.
Threads in different processes can exchange information through shared memory that has been
set up between the two processes.
Thread States:
18
Waiting: A thread enters the Waiting state when (1) it is blocked on an event such as I/O
operation or it voluntarily waits for synchronization purposes
Transition: A thread enters this state after waiting if it is ready to run but the resources
are not available
Terminated: A thread can be terminated by itself, by another thread, or when its parent process
terminates.
PROCESS SYNCHRONIZATION:
19
while (true) {
/* produce an item in next produced */
while (counter == BUFFER SIZE)
; /* do nothing */
buffer[in] = next produced;
in = (in + 1) % BUFFER SIZE;
counter++;
}
The code for the consumer process is
while (true) {
while (counter == 0)
; /* do nothing */
next consumed = buffer[out];
out = (out + 1) % BUFFER SIZE;
counter--;
/* consume the item in next consumed */
}
Suppose that the value of the variable counter is currently 5 and that the producer and consumer
processes concurrently execute the statements “counter++” and “counter--”.
Following the execution of these two statements, the value of the variable counter may be 4, 5, or
6!
The only correct result, though, is counter == 5, which is generated correctly if the producer and
consumer execute separately.
When several processes access and manipulate the same data concurrently the outcome of
the execution depends on the particular order in which the access takes place, is called a
race condition.
To guard against the race condition we need to ensure that only one process at a time can be
manipulating the variable counter.
Each process must request permission to enter its critical section. The section of code
implementing this request is the entry section.
The critical section may be followed by an exit section.
The remaining code is the remainder section.
A solution to the critical-section problem must satisfy the following three requirements:
1. Mutual exclusion. If process Pi is executing in its critical section, then no other processes can
be executing in their critical sections
20
2. Progress. If no process is executing in its critical section and some processes wish to enter
their critical sections, then only those processes that are not executing in their remainder sections
can participate in deciding which will enter its critical section next.
3. Bounded waiting. There exists a bound, or limit, on the number of times that other processes
are allowed to enter their critical sections after a process has made a request to enter its critical
section and before that request is granted.
PETERSON’S SOLUTION:
Peterson’s solution is restricted to two processes that alternate execution between their critical
sections and remainder sections.
The processes are numbered P0 and P1. For convenience, when presenting Pi, we use Pj to denote
the other process.
Peterson’s solution requires the two processes to share two data items:
int turn;
boolean flag[2];
The variable turn indicates whose turn it is to enter its critical section. That is, if turn == i, then
process Pi is allowed to execute in its critical section.
The flag array is used to indicate if a process is ready to enter its critical section. For example, if
flag[i] is true, this value indicates that Pi is ready to enter its critical section.
To enter the critical section, process Pi first sets flag[i] to be true and then sets turn to the value j,
thereby checking that if the other process wishes to enter the critical section, it can do so.
Similarly to enter the critical section, process Pj first sets flag[j] to be true and then sets turn to
the value i, thereby checking that if the other process wishes to enter the critical section.
The solution is correct and thus provides the following.
1. Mutual exclusion is preserved.
2. The progress requirement is satisfied.
3. The bounded-waiting requirement is met.
MUTEX LOCKS:
Mutex locks are used to protect critical regions and thus prevent race conditions
A process must acquire the lock before entering a critical section; it releases the lock when it exits
the critical section.
21
The acquire()function acquires the lock, and the release() function releases the lock.
A mutex lock has a boolean variable available whose value indicates if the lock is available or not.
If the lock is available, a call to acquire() succeeds, and the lock is then considered unavailable.
A process that attempts to acquire an unavailable lock is blocked until the lock is released.
The definition of acquire() is as follows:
acquire() {
while (!available)
; /* busy wait */
available = false;;
}
The definition of release() is as follows:
release()
{
available = true;
}
The main disadvantage of the implementation given here is that it requires busy waiting.
While a process is in its critical section, any other process that tries to enter its critical section
must loop continuously in the call to acquire().
This type of mutex lock is also called a spinlock because the process “spins” while waiting for
the lock to become available.
Busy waiting wastes CPU cycles that some other process might be able to use productively.
Spinlocks do have an advantage, however, in that no context switch is required when a process
must wait on a lock, and a context switch may take considerable time
SEMAPHORES:
A semaphore S is an integer variable that, is accessed only through two standard atomic
operations: wait() and signal().
The wait() operation was originally termed P and the meaning is to test, the signal() was
originally called V and the meaning is to increment.
The definition of wait() is as follows:
wait(S) {
while (S <= 0)
; // busy wait
S--;
}
SEMAPHORE IMPLEMENTATION:
22
The main disadvantage of semaphore is that it requires busy waiting. When one process is in its
critical section any other process that tries to enter the critical section must loop continuously in
the entry code.
The mutual exclusion implementation with semaphores is given by
do
{
wait(mutex);
//critical section
signal(mutex);
//remainder section
}while(TRUE);
To overcome the need for busy waiting, we can modify the wait() and signal() operations.
When a process executes the wait() operation and finds that the semaphore value is not positive, it
must wait. However, rather than engaging in busy waiting, the process can block itself.
The block operation places a process into a waiting queue associated with the semaphore.
Then control is transferred to the CPU scheduler, which selects another process to execute.
A process that is blocked, waiting on a semaphore S, should be restarted when some other process
executes a signal() operation.
The process is restarted by a wakeup() operation, which changes the process fromthe waiting
state to the ready state.
To implement semaphores under this definition, we define a semaphore as follows:
typedef struct {
int value;
struct process *list;
} semaphore
Each semaphore has an integer value and a list of processes list. When a process must wait on a
semaphore, it is added to the list of processes.
A signal() operation removes one process from the list of waiting processes and awakens that
process.
The wait() semaphore operation can be defined as
wait(semaphore *S) {
S->value--;
if (S->value < 0) {
add this process to S->list;
block();
}
}
The signal() semaphore operation can be defined as
signal(semaphore *S) {
S->value++;
if (S->value <= 0) {
remove a process P from S->list;
wakeup(P);
}
}
The Block() and wakeup() operations are provided by the operating system as system calls.
The implementation of a semaphore with waiting queue may result in a situation where two or
more process are waiting indefinitely for an event that can be caused only by one of the waiting
process. This situation is called as deadlock.
Example: Consider a system consisting of two process p0 and p1, each accessing two semaphores
that is set to value 1.
23
24
When a hungry philosopher has both her chopsticks at the same time, she eats without releasing
the chopsticks. When she is finished eating, she puts down both chopsticks.
One simple solution is to represent each chopstick with a semaphore.
A philosopher tries to grab a chopstick by executing a wait() operation on that semaphore. She
releases her chopsticks by executing the signal () operation on the appropriate semaphores.
The shared data is semaphore chopstick [5]; where all the elements of the chopsticks are
initialized to 1.
25
26
Although semaphores provide a convenient and effective mechanism for process synchronization,
using them incorrectly can result in timing errors that are difficult to detect.
EXAMPLE: Suppose that a process interchanges the order in which the wait() and signal()
operations on the semaphore mutex are executed, resulting in the following execution:
signal(mutex);
...
critical section
...
wait(mutex);
In this situation, several processes may be executing in their critical sections simultaneously,
violating the mutual-exclusion requirement.
Suppose that a process replaces signal(mutex) with wait(mutex). That is, it executes
wait(mutex);
...
critical section
...
wait(mutex);
In this case, a deadlock will occur. To deal with such errors one fundamental high-level
synchronization constructs called the monitor type is used.
A monitor type is an ADT that includes a set of programmer defined operations that are provided
with mutual exclusion within the monitor.
The monitor type also declares the variables whose values define the state of an instance of that
type, along with the bodies of functions that operate on those variables.
Thus, a function defined within a monitor can access only those variables declared locally within
the monitor and its formal parameters. Similarly, the local variables of a monitor can be accessed
by only the local functions.
The monitor construct ensures that only one process at a time is active within the monitor.
27
28
When a philosopher gets hungry she tries to pick up the two chopsticks that are closest to her.
A philosopher may pick up only one chopstick at a time. Obviously, she cannot 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
the chopsticks. When she is finished eating, she puts down both chopsticks.
The solution imposes the restriction that a philosopher may pick up her chopsticks only if both of
them are available.
To code this solution, we need to distinguish among three states in which we may find a
philosopher. For this purpose, we introduce the following data structure:
enum {THINKING, HUNGRY, EATING} state[5];
Philosopher i can set the variable state[i] = EATING only if her two neighbors are not eating:
(state[(i+4) % 5] != EATING) and(state[(i+1) % 5] != EATING).
Also declare condition self[5]; that allows philosopher i to delay herself when she is hungry but is
unable to obtain the chopsticks she needs.
Each philosopher, before starting to eat, must invoke the operation pickup().
This may result in the suspension of the philosopher process.
After the successful completion of the operation, the philosopher may eat. Following this, the
philosopher invokes the putdown() operation.
Thus, philosopher i must invoke the operations pickup() and putdown() in the following sequence:
DiningPhilosophers.pickup(i);
eat
DiningPhilosophers.putdown(i);
This solution ensures that no two neighbors are eating simultaneously and that no deadlocks will
occur.
29
Scheduling Algorithms:
CPU scheduling deals with the problem of deciding which of the processes in the ready queue is
to be allocated the CPU. There are many different CPU-scheduling algorithms.
First-Come, First-Served Scheduling
30
Shortest-Job-First Scheduling
Priority Scheduling
Round-Robin Scheduling
Multilevel Queue Scheduling
Multilevel Feedback Queue Scheduling
If the processes arrive in the order P1, P2, P3, and are served in FCFS order, we get the result
shown in the following Gantt chart.
The waiting time is 0 milliseconds for process P1, 24 milliseconds for process P2, and 27
milliseconds for process P3.
Thus, the average waiting time is (0 + 24 + 27)/3 = 17 milliseconds.
If the processes arrive in the order P2, P3, P1, however, the results will be as shown in the
following Gantt chart:
The average waiting time is now (6 + 0 + 3)/3 = 3 milliseconds. Thus, the average waiting time
under an FCFS policy is generally not minimal.
Assume that we have one CPU-bound process and many I/O-bound processes. The CPU-bound
process will get and hold the CPU.
During this time, all the other processes will finish their I/O and will move into the ready queue,
waiting for the CPU.
While the processes wait in the ready queue, the I/O devices are idle.
Now the CPU-bound process finishes its CPU burst and moves to an I/O device. All the I/O-
bound processes, which have short CPU bursts, execute quickly and move back to the I/O queues.
Now the CPU sits idle. This is called as CONVOY EFFECT which results in lower CPU and
device utilization.
The FCFS scheduling algorithm is non preemptive. Once the CPU has been allocated to a process,
that process keeps the CPU until it releases the CPU, either by terminating or by requesting I/O.
ADVANTAGES:
Better for long processes
Simple method (i.e., minimum overhead on processor)
No starvation
DISADVANTAGES:
Waiting time can be large if short requests wait behind the long ones.
31
It is not suitable for time sharing systems where it is important that each user
should get the CPU for an equal amount of time interval.
A proper mix of jobs is needed to achieve good results from FCFS scheduling.
SHORTEST-JOB-FIRST SCHEDULING:
With this algorithm the process that comes with the shortest job will be allocated the CPU first.
This algorithm includes with each process the length of the process’s next CPU burst. When the
CPU is available, it is assigned to the process that has the smallest next CPU burst.
If the next CPU bursts of two processes are the same, FCFS scheduling is used to break the tie.
This is also called as shortest next CPU burst algorithm.
EXAMPLE: consider the following set of processes, with the length of the CPU burst given in
milliseconds:
Using SJF scheduling, we would schedule these processes according to the following Gantt chart:
The waiting time is 3 milliseconds for process P1, 16 milliseconds for process P2, 9 milliseconds
for process P3, and 0 milliseconds for process P4.
Thus, the average waiting time is (3 + 16 + 9 + 0)/4 = 7 milliseconds.
The SJF algorithm can be either preemptive or nonpreemptive.
When a new process arrives at the ready queue while a previous process is still executing and the
next CPU burst of the newly arrived process is shorter than what is left of the currently executing
process, then a preemptive or non preemptive approach can be chosen.
A preemptive SJF algorithm will preempt the currently executing process.
A nonpreemptive SJF algorithm will allow the currently running process to finish its CPU burst.
Preemptive SJF scheduling is sometimes called shortest-remaining-time-first scheduling.
EXAMPLE: consider the following four processes, with the length of the CPU burst given in
milliseconds:
Process P1 is started at time 0, since it is the only process in queue. Process P2 arrives at time 1.
The remaining time for process P1 (7 milliseconds) is larger than the time required by process P2
(4 milliseconds), so process P1 is preempted, and process P2 is scheduled.
The average waiting time is [(10 − 1) + (1 − 1) + (17 − 2) + (5 − 3)]/4 = 26/4 = 6.5 milliseconds.
Nonpreemptive SJF scheduling would result in an average waiting time of 7.75 milliseconds
32
ADVNATAGES:
The SJF scheduling algorithm has minimum average waiting time for a given set
of processes.
Gives superior turnaround time performance to shortest process next because a
short job is given immediate preference to a running longer job.
Throughput is high.
DISADVANTAGES:
The difficulty with the SJF algorithm is knowing the length of the next CPU
request
Starvation may be possible for the longer processes.
PRIORITY SCHEDULING:
Apriority is associated with each process, and the CPU is allocated to the process with the highest
priority.
Equal-priority processes are scheduled in FCFS order.
An SJF algorithm is simply a priority algorithm where the priority (p) is the inverse of the
(predicted) next CPU burst.
As an example, consider the following set of processes, assumed to have arrived at time 0 in the
order P1, P2, · · ·, P5, with the length of the CPU burst given in milliseconds:
Using priority scheduling, we would schedule these processes according to the following Gantt
chart:.
33
EXAMPLE: Consider the following set of processes that arrive at time 0, with the length of the
CPU burst given in milliseconds:
If we use a time quantum of 4 milliseconds, then process P1 gets the first 4 milliseconds. Since it
requires another 20 milliseconds, it is preempted after the first time quantum, and the CPU is
given to the next process in the queue, process P2
Process P2 does not need 4 milliseconds, so it quits before its time quantum expires.
The CPU is then given to the next process, process P3. Once each process has received 1 time
quantum, the CPU is returned to process P1 for an additional time quantum.
P1 waits for 6 milliseconds (10 - 4), P2 waits for 4 milliseconds, and P3 waits for 7 milliseconds.
Thus, the average waiting time is 17/3 = 5.66 milliseconds.
The performance of the RR algorithm depends heavily on the size of the time quantum.
If the time quantum is extremely large, the RR policy is the same as the FCFS policy.
If the time quantum is extremely small the RR approach can result in a large number of context
switches.
ADVANTAGES:
Does not suffer by starvation.
DISADVANTAGE:
The average waiting time under the RR policy is often long.
There is Low throughput.
There are Context Switches.
MULTI LEVEL QUEUE SCHEDULING:
The processes are divided into foreground process and background process.
These two types of processes have different response-time requirements and have different
scheduling needs.
The foreground processes may have priority over background processes.
A multilevel queue scheduling algorithm partitions the ready queue into several separate queues.
The processes are permanently assigned to one queue, generally based on some property of the
process, such as memory size, process priority, or process type.
34
Example of a multilevel queue scheduling algorithm with five queues, in order of priority:
1. System processes
2. Interactive processes
3. Interactive editing processes
4. Batch processes
5. Student processes
Each queue has its own scheduling algorithm. For example, separate queues might be used for
foreground and background processes.
The foreground queue might be scheduled by an RR algorithm, while the background queue is
scheduled by an FCFS algorithm.
There must be scheduling among the queues, which is commonly implemented as fixed-priority
preemptive scheduling.
No process in the batch queue, for example, could run unless the queues for system processes,
interactive processes, and interactive editing processes were all empty.
If an interactive editing process entered the ready queue while a batch process was running, the
batch process would be preempted.
The scheduler first executes all processes in queue 0. Only when queue 0 is empty will it execute
processes in queue 1. Similarly, processes in queue 2 will be executed only if queues 0 and 1 are
empty.
A process that arrives for queue 1 will preempt a process in queue 2. A process in queue 1 will in
turn be preempted by a process arriving for queue 0.
A process entering the ready queue is put in queue 0. A process in queue 0 is given a time
quantum of 8 milliseconds.
35
If it does not finish within this time, it is moved to the tail of queue 1. If queue 0 is empty, the
process at the head of queue 1 is given a quantum of 16 milliseconds.
If it does not complete, it is preempted and is put into queue 2. Processes in queue 2 are run on an
FCFS basis but are run only when queues 0 and 1 are empty. a multilevel feedback queue
DEADLOCKS:
A process requests resources; if the resources are not available at that time, the process enters a
waiting state. Sometimes, a waiting process is never again able to change state, because the
resources it has requested are held by other waiting processes. This situation is called a deadlock.
The resources of a computer system may be partitioned into several types such as CPU cycles,
files, and I/O devices (such as printers and DVD drives)
A process must request a resource before using it and must release the resource after using it.
A process may utilize a resource in only the following sequence.
o Request. The process requests the resource. If the request cannot be granted immediately
then the requesting process must wait until it can get the resource.
o Use. The process can operate on the resource
o Release. The process releases the resource.
36
37
If a resource-allocation graph does not have a cycle, then the system is not in a deadlocked state.
If there is a cycle, then the system may or may not be in a deadlocked state.
DEADLOCK AVOIDANCE:
38
.Deadlock avoidance requires that the operating system be given additional information in
advance concerning which resources a process will request and use during its lifetime.
SAFE STATE:
A state is safe if the system can allocate resources to each process in some order and still avoid a
deadlock.
A system is in a safe state only if there exists a safe sequence.
A safe state is not a deadlocked state. Conversely, a deadlocked state is an unsafe state.
Not all unsafe states are deadlocks; however an unsafe state may lead to a deadlock.
A sequence of processes <P1, P2, ..., Pn> is a safe sequence for the current allocation state if,
the resource requests that Pi make can be satisfied by the currently available resources plus the
resources held by all Pj, with j < i.
Example: consider a system with twelve magnetic tape drives and three processes: P0, P1, and P2
Process P0 requires ten tape drives, process P1 may need as many as four tape drives, and
process P2 may need up to nine tape drives.
Suppose that, at time t0, process P0 is holding five tape drives, process P1 is holding two tape
drives, and process P2 is holding two tape drives
At time t0, the system is in a safe state. The sequence <P1, P0, P2> satisfies the safety condition.
Process P1 can immediately be allocated all its tape drives and then return them (the system will
then have five available tape drives);
Then process P0 can get all its tape drives and return them (the system will then have ten
available tape drives); and finally process P2 can get all its tape drives and return them (the
system will then have all twelve tape drives available).
RESOURCE ALLOCATION GRAPH:
A new type of edge, called a claim edge is used in resource allocation graph.
A claim edge Pi → Rj indicates that process Pi may request resource Rj at some time in the future.
When process Pi requests resource Rj , the claim edge Pi → Rj is converted to a request edge.
When a resource Rj is released by Pi, the assignment edge Rj → Pi is reconverted to claim edge
Pi ->Rj
39
Now suppose that process Pi requests resource Rj. The request can be granted only if converting
the request edge Pi → Rj to an assignment edge Rj → Pi does not result in the formation of a
cycle in the resource-allocation graph.
If no cycle exists, then the allocation of the resource will leave the system in a safe state. If a
cycle is found, then the allocation will put the system in an unsafe state.
BANKERS ALGORITHM:
When a new process enters the system, it must declare the maximum number of instances of each
resource type that it may need.
This number may not exceed the total number of resources in the system.
When a user requests a set of resources, the system must determine whether the allocation of
these
resources will leave the system in a safe state.
If it will, the resources are allocated; otherwise, the process must wait until some other process
releases enough resources.
The following data structures are needed to implement bankers algorithm, where n is the number
of
processes in the system and m is the number of resource types:
• Available: Length m indicates the number of available resources of each type.
• Max. An n × m matrix defines the maximum demand of each process.
• Allocation. An n × m matrix defines the number of resources of each type currently allocated.
• Need. An n × m matrix indicates the remaining resource need of each process.
1. SAFETY ALGORITHM:
It is an algorithm for finding out whether or not a system is in a safe state
1) LetWork and Finish be vectors of length m and n, respectively. Initialize Work = Available and
Finish[i] = false for i = 0, 1, ..., n − 1.
2) Find an index i such that both
a. Finish[i] == false
b. Needi ≤Work
If no such i exists, go to step 4
3) Work =Work + Allocationi
Finish[i] = true
Go to step 2.
4) If Finish[i] == true for all i, then the system is in a safe state.
This algorithm may require an order of m × n2 operations to determine whether a state is safe.
2. RESOURCE REQUEST ALGORITHM:
This is an algorithm for determining whether requests can be safely granted.
Let Requesti be the request vector for process Pi.
1. If Requesti ≤Needi , go to step 2. Otherwise, raise an error condition, since the process has
exceeded its maximum claim.
2. If Requesti ≤ Available, go to 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 ;
If the resulting resource-allocation state is safe, the transaction is completed, and process Pi is
allocated its resources.
However, if the new state is unsafe, then Pi must wait for Requesti , and the old resource-
allocation state is restored.
40
DEADLOCK DETECTION:
A Deadlock detection algorithm examines the state of the system to determine whether a deadlock has
occurred
SINGLE INSTANCE OF EACH RESOURCE TYPE:
If all resources have only a single instance, then we can define a deadlock detection algorithm
that uses a variant of the resource-allocation graph, called a wait-for graph.
This graph is obtained from the resource-allocation graph by removing the resource nodes and
collapsing the appropriate edges.
A deadlock exists in the system if and only if the wait-for graph contains a cycle.
To detect deadlocks, the system needs to maintain the wait for graph and periodically invoke an
algorithm that searches for a cycle in the graph.
SEVERAL INSTANCE OF RESOURCE TYPE:
The wait-for graph scheme is not applicable to a resource-allocation system with multiple
instances of each resource type
This algorithm uses the following data structure,
• Available. A vector of length m indicates the number of available resources of each type.
• Allocation. An n × m matrix defines the number of resources currently allocated to each process.
• Request. An n × m matrix indicates the current request of each process.
1. LetWork and Finish be vectors of length m and n, respectively. Initialize Work = Available. For i = 0,
1, ..., n–1, if Allocationi _= 0, then Finish[i] = false. Otherwise, Finish[i] = true.
2. Find an index i such that both
a. Finish[i] == false
b. Requesti ≤Work
If no such i exists, go to step 4.
3. Work =Work + Allocationi
Finish[i] = true
Go to step 2.
4. If Finish[i] ==false for some i, 0≤i<n, then the system is in a deadlocked state.
Moreover, if Finish[i] == false, then process Pi is deadlocked.
This algorithm requires an order of m × n2 operations to detect whether the system is in a deadlocked
state.
DEADLOCK RECOVERY:
When a detection algorithm determines that a deadlock exists ,the possibility is to let the system
recover from the deadlock automatically
There are two options for breaking a deadlock.
1. PROCESS TERMINATION:
It is the process of eliminating the deadlock by aborting a process. It involves two methods
i) Abort all deadlocked process: This method breaks the deadlock cycle but with a greater
expense.
41
ii) Abort one process at a time until the deadlock cycle is eliminated: This method aborts
the deadlocked process one by one and after each process is aborted, it checks whether
any process are still deadlocked.
2. RESOURCE PREEMPTION:
To eliminate deadlocks Preempt some resources from the process and give the resource to other
process until the deadlock cycle is broken.
i) Selecting an victim: It is the process of selecting which resource and which process are
to be preempted.
ii) Rollback: If we preempt a resource from a process, it cannot continue with its normal
execution; it is missing some needed resource. We must roll back the process to some
safe state and restart it from that state.
iii) Starvation: The resources will not always be preempted from the same process, else it
leads to starvation.