You are on page 1of 52

Chapter 3: Processes

Chapter 3: Processes
Process Concept
Process Scheduling
Operations on Processes
Interprocess Communication
Examples of IPC Systems
Communication in Client-Server Systems
Objectives
To introduce the notion of a process -- a program in
execution, which forms the basis of all computation

To describe the various features of processes, including


scheduling, creation and termination, and communication

To describe communication in client-server systems


Process Concept
An operating system executes a variety of programs:
Batch system jobs
Time-shared systems user programs or tasks

Textbook uses the terms job and process almost interchangeably

Process a program in execution; process execution must


progress in sequential fashion

A process includes:
program counter
stack
data section
The Process
Multiple parts
The program code, also called text section
Current activity including program counter, processor registers
Stack containing temporary data
Function parameters, return addresses, local variables
Data section containing global variables
Heap containing memory dynamically allocated during run time
Program is passive entity, process is active
Program becomes process when executable file loaded into memory
Execution of program started via GUI mouse clicks, command line
entry of its name, etc
One program can be several processes
Consider multiple users executing the same program
Process in Memory
Process State
As a process executes, it changes state
new: The process is being created
running: Instructions are being executed
waiting: The process is waiting for some event to occur
ready: The process is waiting to be assigned to a processor
terminated: The process has finished execution
Diagram of Process State
Process Control Block (PCB)
Information associated with each process
Process state
Program counter
CPU registers
CPU scheduling information
Memory-management information
Accounting information
I/O status information
Process Control Block (PCB)
CPU Switch From Process to Process
Process Scheduling

Maximize CPU use, quickly switch processes onto CPU for


time sharing
Process scheduler selects among available processes for next
execution on CPU
Maintains scheduling queues of processes
Job queue set of all processes in the system
Ready queue set of all processes residing in main memory, ready
and waiting to execute
Device queues set of processes waiting for an I/O device
Processes migrate among the various queues
Schedulers
Long-term scheduler (or job scheduler) selects which
processes should be brought into the ready queue
Short-term scheduler (or CPU scheduler) selects which
process should be executed next and allocates CPU
Sometimes the only scheduler in a system
Schedulers (Cont.)
Short-term scheduler is invoked very frequently (milliseconds)
(must be fast)

Long-term scheduler is invoked very infrequently (seconds,


minutes) (may be slow)

The long-term scheduler controls the degree of


multiprogramming

Processes can be described as either:


I/O-bound process spends more time doing I/O than computations,
many short CPU bursts
CPU-bound process spends more time doing computations; few very
long CPU bursts
Context Switch
When CPU switches to another process, the system must save the
state of the old process and load the saved state for the new
process via a context switch.

Context of a process represented in the PCB

Context-switch time is overhead; the system does no useful work


while switching
The more complex the OS and the PCB -> longer the context switch

Time dependent on hardware support


Some hardware provides multiple sets of registers per CPU -> multiple
contexts loaded at once
Process Creation
Parent process create children processes, which, in turn create
other processes, forming a tree of processes

Generally, process identified and managed via a process identifier


(pid)

Resource sharing
Parent and children share all resources
Children share subset of parents resources
Parent and child share no resources

Execution
Parent and children execute concurrently
Parent waits until children terminate
Process Creation (Cont.)

Address space
Child duplicate of parent
Child has a program loaded into it

UNIX examples
fork system call creates new process
exec system call used after a fork to replace the process memory space with
a new program
Process Creation
Process Termination
Process executes last statement and asks the operating system to
delete it (exit)
Output data from child to parent (via wait)
Process resources are deallocated by operating system

Parent may terminate execution of children processes (abort)


Child has exceeded allocated resources
Task assigned to child is no longer required
If parent is exiting
Some operating systems do not allow child to continue if its parent terminates
All children terminated - cascading termination
Interprocess Communication
Processes within a system may be independent or cooperating
Cooperating process can affect or be affected by other processes,
including sharing data
Reasons for cooperating processes:
Information sharing
Computation speedup
Modularity
Convenience
Cooperating processes need interprocess communication (IPC)
Two models of IPC
Shared memory
Message passing
Communications Models
Cooperating Processes
Independent process cannot affect or be affected by the execution
of another process

Cooperating process can affect or be affected by the execution of


another process

Advantages of process cooperation


Information sharing
Computation speed-up
Modularity
Convenience
Producer-Consumer Problem

Paradigm for cooperating processes, producer process


produces information that is consumed by a consumer
process
unbounded-buffer places no practical limit on the size of the
buffer
bounded-buffer assumes that there is a fixed buffer size
Interprocess Communication
Message Passing

Mechanism for processes to communicate and to synchronize their


actions
Message system processes communicate with each other without
resorting to shared variables
IPC facility provides two operations:
send(message) message size fixed or variable
receive(message)
If P and Q wish to communicate, they need to:
establish a communication link between them
exchange messages via send/receive
Implementation of communication link
physical (e.g., shared memory, hardware bus)
logical (e.g., logical properties)
Direct Communication
Processes must name each other explicitly:
send (P, message) send a message to process P
receive(Q, message) receive a message from process Q

Properties of communication link


Links are established automatically
A link is associated with exactly one pair of communicating processes
Between each pair there exists exactly one link
The link may be unidirectional, but is usually bi-directional
Indirect Communication
Messages are directed and received from mailboxes (also referred
to as ports)
Each mailbox has a unique id
Processes can communicate only if they share a mailbox

Properties of communication link


Link established only if processes share a common mailbox
A link may be associated with many processes
Each pair of processes may share several communication links
Link may be unidirectional or bi-directional
Indirect Communication
Operations
create a new mailbox
send and receive messages through mailbox
destroy a mailbox

Primitives are defined as:


send(A, message) send a message to mailbox A
receive(A, message) receive a message from mailbox A
Synchronization
Message passing may be either blocking or non-blocking

Blocking is considered synchronous


Blocking send has the sender block until the message is received
Blocking receive has the receiver block until a message is available

Non-blocking is considered asynchronous


Non-blocking send has the sender send the message and continue
Non-blocking receive has the receiver receive a valid message or null
Buffering
Queue of messages attached to the link; implemented in one of
three ways
1. Zero capacity 0 messages
Sender must wait for receiver
2. Bounded capacity finite length of n messages
Sender must wait if link full
3. Unbounded capacity infinite length
Sender never waits
ProducerConsumer Problem
In computing, the producerconsumer 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, who share a common, fixed-size buffer used as a queue.
The producer's job is to generate a piece of 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.
The problem is 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.
ProducerConsumer Problem
The solution for 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.
The solution can be reached by means of inter-process
communication, typically using semaphores.
An inadequate solution could result in a deadlock where both
processes are waiting to be awakened. The problem can also be
generalized to have multiple producers and consumers.
Producer Procedure
int itemCount = 0;
procedure producer()
{
while (true) { item = produceItem();
if (itemCount == BUFFER_SIZE) { sleep();
}
putItemIntoBuffer(item);
itemCount = itemCount + 1;
if (itemCount == 1)
{ wakeup(consumer);
}
}
}
procedure consumer()
{
while (true)
{
if (itemCount == 0)
{
sleep();
}
item = removeItemFromBuffer();
itemCount = itemCount - 1;
if (itemCount == BUFFER_SIZE - 1) { wakeup(producer);
}
consumeItem(item);
}
}
Problems in Producer-Consumer Algorithm
The problem with this solution is that it contains a race condition that can lead to
a deadlock. Consider the following scenario:
The consumer has just read the variable itemCount, noticed it's zero and is just
about to move inside the if block.
Just before calling sleep, the consumer is interrupted and the producer is
resumed.
The producer creates an item, puts it into the buffer, and increases itemCount.
Because the buffer was empty prior to the last addition, the producer tries to
wake up the consumer.
Unfortunately the consumer wasn't yet sleeping, and the wakeup call is lost.
When the consumer resumes, it goes to sleep and will never be awakened again.
This is because the consumer is only awakened by the producer
whenitemCount is equal to 1.
The producer will loop until the buffer is full, after which it will also go to sleep.
Since both processes will sleep forever, we have run into a deadlock. This solution
therefore is unsatisfactory.
Mutual exclusion

Mutual exclusion refers to the requirement of ensuring that no


two concurrent processes are in their critical section at the same
time;
It is a basic requirement in concurrency control, to prevent race
conditions.
Here, a critical section refers to a period when the process accesses a
shared resource, such as shared memory.
Hardware solutions
On uniprocessor systems, the simplest solution to achieve mutual
exclusion is to disable interrupts during a process's critical section.
This will prevent any interrupt service routines from running
(effectively preventing a process from being preempted). Although
this solution is effective, it leads to many problems.
Busy-waiting is effective for both uniprocessor and multiprocessor
systems. The use of shared memory and an atomic test-and-
set instruction provides the mutual exclusion. A process can test-and-
set on a location in shared memory, and since the operation is atomic,
only one process can set the flag at a time. Any process that is
unsuccessful in setting the flag can either go on to do other tasks and
try again later, release the processor to another process and try again
later, or continue to loop while checking the flag until it is successful
in acquiring it.
Software solutions

Beside hardware-supported solutions, some software solutions exist


that use busy waiting to achieve mutual exclusion. Examples of these
include the following:
Dekker's algorithm
Peterson's algorithm
Lamport's bakery algorithm
Szymanski's Algorithm
Taubenfeld's black-white bakery algorithm.
The Critical-Section Problem
n processes competing to use some shared data.
No assumptions may be made about speeds or the number of CPUs.
Each process has a code segment, called Critical Section (CS), in which the
shared data is accessed.
Problem ensure that when one process is executing in its CS, no other
process
is allowed to execute in its CS.
When a process executes code that manipulates shared data (or resource),
we say that the process is in its Critical Section (for that shared data).
The execution of critical sections must be mutually exclusive: at any time,
only one process is allowed to execute in its critical section (even with
multiple processors).
So each process must first request permission to enter its critical section.
CS Problem Dynamics

The section of code implementing this request is called the Entry


Section (ES).
The critical section (CS) might be followed by a Leave/Exit Section
(LS).
The remaining code is the Remainder Section (RS).
The critical section problem is to design a protocol that the processes
can use so that their action will not depend on the order in which
their execution is interleaved (possibly on many processors).
Solution to Critical-Section Problem

There are 3 requirements that must stand for a correct solution:


1. Mutual Exclusion
2. Progress
3. Bounded Waiting
Types of solutions to CS problem

Software solutions
algorithms whos correctness does not rely on any other assumptions.
Hardware solutions
rely on some special machine instructions.
Operating System solutions
provide some functions and data structures to the programmer through
system/library calls.
Programming Language solutions
Linguistic constructs provided as part of a language
Dekker's algorithm
Dekker's algorithm is the first known correct solution to the mutual
exclusion problem in concurrent programming. The solution is attributed
to Dutch mathematician Th. J. Dekker by Edsger W. Dijkstra in his
manuscript on cooperating sequential processes.
It allows two threads to share a single-use resource without conflict, using
only shared memory for communication.

If two processes attempt to enter a critical section at the same time, the
algorithm will allow only one process in, based on whose turn it is.
If one process is already in the critical section, the other process will busy
wait for the first process to exit.
This is done by the use of two flags, flag[0] and flag[1], which indicate an
intention to enter the critical section and a turn variable that indicates who
has priority between the two processes.
Peterson's algorithm
Peterson's algorithm is a concurrent programming algorithm developed by
Gary L. Peterson in a 1981 paper. It is known as a simple algorithm when
compared to others. Peterson proved the algorithm using both the 2-
process case and the N-process case.
Peterson's algorithm is used for mutual exclusion and allows two processes
to share a single-use resource without conflict. It uses only shared memory
for communication. Peterson's formula originally worked only with two
processes, but has since been generalized for more than two.
Just as in Dekker's algorithm, turn variables (turn) and status flags (flag) are
conditions or variables that are used in Peterson's algorithm. Because of
these two conditions, and because of waiting for a turn only if other flags
are set, the need to clear and reset flags is avoided. After a flag is set, the
turn is immediately given away when using Peterson's algorithm.
Semaphore

In computer science, particularly in operating systems,


a semaphore is a variable or abstract data type that is used for
controlling access, by multiple processes, to a common resource in
a parallel programming or a multi user environment.
Semaphores are a useful tool in the prevention of race conditions;
however, their use is by no means a guarantee that a program is free
from these problems.
Semaphores which allow an arbitrary resource count are
called counting semaphores, while semaphores which are restricted
to the values 0 and 1 (or locked/unlocked, unavailable/available) are
called binary semaphores.
Dining Philosophers Problem

In computer science, the dining philosophers problem is an example


problem often used in concurrent algorithm design to
illustrate synchronization issues and techniques for resolving them.
It was originally formulated in 1965 by Edsger Dijkstra as a student
exam exercise, presented in terms of computers competing for
access to tape drive peripherals.
Dining Philosophers Problem
Problem statement
Five silent philosophers sit at a round table with bowls of spaghetti. Forks
are placed between each pair of adjacent philosophers.
Each philosopher must alternately think and eat. However, a philosopher
can only eat spaghetti when he has both left and right forks. Each fork can
be held by only one philosopher and so a philosopher can use the fork only
if it's not being used by another philosopher.
After he finishes eating, he needs to put down both forks so they become
available to others. A philosopher can grab the fork on his right or the one
on his left as they become available, but can't start eating before getting
both of them.
Eating is not limited by the amount of spaghetti left: assume an infinite
supply.
The problem is how to design a discipline of behavior
(a concurrent algorithm) such that each philosopher won't starve.
Problems

The problem was designed to illustrate the challenges of


avoiding deadlock, a system state in which no progress is possible. To
see that a proper solution to this problem isn't obvious, consider a
proposal in which each philosopher is instructed to behave as follows:
think until the left fork is available; when it is, pick it up;
think until the right fork is available; when it is, pick it up;
when both forks are held, eat for a fixed amount of time;
then, put the right fork down;
then, put the left fork down;
repeat from the beginning.
Sleeping barber problem
Sleeping barber problem
The sleeping barber problem is a classic inter-process
communication and synchronization problem between multiple operating
system processes. The problem is analogous to that of keeping a barber
working when there are customers, resting when there are none and doing
so in an orderly manner.
The analogy is based upon a hypothetical barber shop with one barber. The
barber has one barber chair and a waiting room with a number of chairs in
it. When the barber finishes cutting a customer's hair, he dismisses the
customer and then goes to the waiting room to see if there are other
customers waiting. If there are, he brings one of them back to the chair and
cuts his hair. If there are no other customers waiting, he returns to his chair
and sleeps in it.
Each customer, when he arrives, looks to see what the barber is doing. If the
barber is sleeping, then the customer wakes him up and sits in the chair. If
the barber is cutting hair, then the customer goes to the waiting room. If
there is a free chair in the waiting room, the customer sits in it and waits his
turn. If there is no free chair, then the customer leaves.
Sleeping barber problem
Based on a nave analysis, the above description should ensure that the shop functions
correctly, with the barber cutting the hair of anyone who arrives until there are no more
customers, and then sleeping until the next customer arrives. In practice, there are a
number of problems that can occur that are illustrative of general scheduling problems.
The problems are all related to the fact that the actions by both the barber and the
customer (checking the waiting room, entering the shop, taking a waiting room chair, etc.)
all take an unknown amount of time. For example, a customer may arrive and observe that
the barber is cutting hair, so he goes to the waiting room.
While he is on his way, the barber finishes the haircut he is doing and goes to check the
waiting room. Since there is no one there (the customer not having arrived yet), he goes
back to his chair and sleeps.
The barber is now waiting for a customer and the customer is waiting for the barber. In
another example, two customers may arrive at the same time when there happens to be a
single seat in the waiting room.
They observe that the barber is cutting hair, go to the waiting room, and both attempt to
occupy the single chair.
End of Chapter 3

You might also like