Unit 2
Unit 2
Processes
Process Concept
Process Scheduling
Operations on Processes
Inter process Communication
Threads
Overview
Multithreading Models
CPU Scheduling
Basic Concepts
Scheduling Criteria
Scheduling Algorithms
Multiple-Processor Scheduling
Linux
Process utilities
Library Functions
System Calls related to process
Process Concept
Process is a program in execution; process execution must progress in sequential
fashion.
Execution of program started via GUI mouse clicks, command line entry of its name,
etc
• Process state. The state may be new, ready, running, waiting, halted, and so on.
Program counter. The counter indicates the address of the next instruction to be
executed for this process.
Process Control Block
• CPU registers. The registers include accumulators, index registers,
stack pointers, and general-purpose registers, plus any condition-code
information. Along with the program counter.
In brief, the PCB simply serves as the repository for any information
that may vary from process to process.
CPU switch from process to process
Process Scheduling
The objective of multiprogramming is to have some process running at all times, to
maximize CPU utilization.
The objective of time sharing is to switch the CPU among processes so frequently
that users can interact with each program while it is running.
For a single-processor system, there will never be more than one running process. If
there are more processes, the rest will have to wait until the CPU is free and can be
rescheduled
Process scheduler selects among available processes for next execution on CPU
Each rectangular box represents a queue. Two types of queues are present: the
ready queue and a set of device queues.
The circles represent the resources that serve the queues, and the arrows indicate
the flow of processes in the system.
A new process is initially put in the ready queue. It waits there until it is selected for
execution, or is dispatched. Once the process is allocated the CPU and is executing,
one of several events could occur:
Representation of Process Scheduling
•The process could issue an I/O request and then be placed in an I/O queue.
• The process could create a new subprocess and wait for the subprocess'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.
In the first two cases, the process eventually switches from the waiting state to the ready
state and is then put back in the ready queue. A process continues this cycle until it
terminates, at which time it is removed from all queues and has its PCB and resources
deallocated.
Schedulers
A process may create several new processes, via a create-process system call during
the course of execution. The creating process is called a parent process, and the new
processes are called the children of that process. Each of these new processes may in
turn create other processes, forming a tree of processes.
Most operating systems (including UNIX and the Windows family of operating
systems) identify processes according to a unique process identifier (or pid), which is
typically an integer number.
In general, a process will need certain resources (CPU time, memory, files, 1/0
devices) to accomplish its task. When a process creates a subprocess, that subprocess
may be able to obtain its resources directly from the operating system, or it may be
constrained to a subset of the resources of the parent process.
The parent may have to partition its resources among its children, or it may be able
to share some resources (such as memory or files) among several of its children.
Restricting a child process to a subset of the parent's resources prevents any process
from overloading the system by creating too many subprocesses.
Resource sharing options
1. Parent and children share all resources
2. Children share subset of parent’s resources
3. Parent and child share no resources
When a process creates a new process, two possibilities exist in terms of execution:
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 possibilities in terms of the address space of the new process:
1. The child process is a duplicate of the parent process (it has the same program and
data as the parent).
2. The child process has a new 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
C Program Forking Separate Process
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 (via the wait()
system call). All the resources of the process-including physical and virtual memory,
open files, and I/O buffers-are deallocated by the operating system.
Termination can occur in other circumstances as well. A process can cause the
termination of another process using abort() system call , Usually, such a system call
can be invoked only by the parent of the process that is to be terminated.
A parent may terminate the execution of one of its children for a variety of reasons,
such as these:
• The child has exceeded its usage of some of the resources that it has been
allocated.
• The parent is exiting, and the operating system does not allow a child to
continue if its parent terminates.
Process Termination
Some operating systems do not allow child to exists if its parent has terminated. If a
process terminates, then all its children must also be terminated.
• cascading termination. All children, grandchildren, etc. are terminated.
• The termination is initiated by the operating system.
The parent process may wait for termination of a child process by using the
wait()system call. The call returns status information and the pid of the terminated
process
pid = wait(&status);
There are several reasons for providing an environment that allows process
– Information sharing. Since several users may be interested in the same piece
of information (for instance, a shared file), we must provide an environment
to allow concurrent access to such information.
– Computation speedup. If we want a particular task to run faster, we must
break it into subtasks, each of which will be executing in parallel with the
others.
– Modularity. We may want to construct the system in a modular fashion,
dividing the system functions into separate processes or threads.
– Convenience. Even an individual user may work on many tasks at the same
time. For instance, a user may be editing, printing, and compiling in parallel.
Interprocess Communication
Cooperating processes require an interprocess communication (IPC) mechanism
that will allow them to exchange data and Information.
Two models of IPC 1. Shared memory 2. Message passing
In the shared-memory model, a region of memory that is shared by cooperating
processes is established. Processes can then exchange information by reading
and writing data to the shared region.
In the message passing model, communication takes place by means of messages
exchanged between the cooperating processes.
Message passing is easier to implement than is shared memory for inter
computer communication.
Shared memory is faster than message passing, as message-passing systems are
typically implemented using system calls and thus require the more time
consuming task of kernel intervention.
In contrast, in shared-memory systems, system calls are required only to
establish shared-memory regions. Once shared memory is established, all
accesses are treated as routine memory accesses, and no assistance from the
kernel is required.
Communications Models
(a) Message passing. (b) shared memory.
Shared Memory Systems
Recall that, normally, the operating system tries to prevent one process from
accessing another process's memory. Shared memory requires that two or more
processes agree to remove this restriction. They can then exchange information
by reading and writing data in the shared areas. The form of the data and the
location are determined by these processes and are not under the operating
system's control.
The processes are also responsible for ensuring that they are not writing to the
same location simultaneously.
The producer-consumer problem also provides a useful metaphor for the client-
server paradigm. We generally think of a server as a producer and a client as a
consumer. For example, a web server produces (that is, provides) HTML files and
images, which are consumed (that is, read) by the client web browser requesting
the resource.
A producer can produce one item while the consumer is consuming another item. The
producer and consumer must be synchronized, so that the consumer does not try to
consume an item that has not yet been produced.
Two types of buffers can be used. 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;
Producer – Consumer Problem
The shared buffer is implemented as a circular array with two logical pointers: in and out.
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) % BUFFERSIZE) == out
The producer process has a local variable nextProduced in which the new item to be
produced is stored. The consumer process has a local variable nextConsumed in which
the item to be consumed is stored.
Bounded-Buffer – Producer
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;
}
Bounded-Buffer – Consumer
item next_consumed;
while (true) {
while (in == out)
; /* do nothing */
next_consumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
• There are several methods for logically implementing a link and the
send()/receive() operations:
• Direct or indirect communication
• Synchronous or asynchronous communication
• Automatic or explicit buffering
• Implementation issues:
– How are links established?
– Can a link be associated with more than two processes?
– How many links can there be between every pair of communicating
processes?
– What is the capacity of a link?
– Is the size of a message that the link can accommodate fixed or variable?
– Is a link unidirectional or bi-directional?
Direct Communication
• In direct communication, each process that wants to communicate must explicitly
name the recipient or sender of the communication. In this scheme, the send ()
and receive ()primitives are defined as:
– send (P, message) – send a message to process P
– receive(Q, message) – receive a message from process Q
• This scheme exhibits symmetry in addressing; that is, both the sender process
and the receiver process must name the other to communicate. A variant of this
scheme employs asymmetry in addressing. Here, only the sender names the
recipient; the recipient is not required to name the sender.
Direct Communication
• In this scheme, the send () and receive() primitives are defined as follows:
– send(P, message) -Send a message to process P.
– receive (id, message) -Receive a message from any process; the variable id is
set to the name of the process with which communication has taken place.
• Changing the identifier of a process may necessitate examining all other process
definitions. All references to the old identifier must be found, so that they can be
modified to the new identifier.
• In general, any such hard-coding techniques, here identifiers must be explicitly
stated, are less desirable than techniques involving indirection,
Indirect Communication
In indirect communication, the messages are sent to and received from mailboxes, or
ports.
A mailbox can be viewed abstractly as an object into which messages can be placed by
processes and from which messages can be removed.
Each mailbox has a unique identification. In this scheme, a process can communicate
with some other process via a number of different mailboxes. Two processes can
communicate only if the processes have a shared mailbox, however. The send() and
receive () primitives are defined as follows:
send (A, message) -Send a message to mailbox A.
receive (A, message) -Receive a message from mailbox A.
If the mailbox is owned by a process (that is, the mailbox is part of the address space
of the process), then we distinguish between the owner (who can only receive
messages through this mailbox) and the user (who can only send messages to the
mailbox). When a process that owns a mailbox terminates/ the mailbox disappears.
Any process that subsequently sends a message to this mailbox must be notified that
the mailbox no longer exists.
In contrast/ a mailbox that is owned by the operating system has an existence of its
own. It is independent and is not attached to any particular process. The operating
system then must provide a mechanism that allows a process to do the following:
• create a new mailbox (port)
• send and receive messages through mailbox
• delete a mailbox
The process that creates a new mailbox is that mailbox's owner by default. Initially,
the owner is the only process that can receive messages through this mailbox.
However, the ownership and receiving privilege may be passed to other processes
through appropriate system calls. Of course/ this provision could result in multiple
receivers for each mailbox.
Synchronization
• Communication between processes takes place through calls to send () and receive
() primitives. There are different design options for implementing each primitive.
Message passing may be either blocking or non-blocking also known as synchronous
and asynchronous.
1. Zero capacity – The queue has a maximum length of zero; thus, the link cannot
have any messages waiting in it. In this case, the sender must block until the
recipient receives the message.(rendezvous). This is a system with no buffering.
2. Bounded capacity – The queue has finite length n; thus, at most n messages can
reside in it. If the queue is not full when a new message is sent, the message is
placed in the queue and the sender can continue execution without waiting. If
the link is full, the sender must block until space is available in the queue. This is
a system with bounded buffering
A busy web server may have several (perhaps thousands) of clients concurrently
accessing it. If the web server ran as a traditional single-threaded process, it would be
able to service only one client at a time.
One solution is to have the server run as a single process that accepts requests. When the
server receives a request, it creates a separate process to service that request.
Threads also play a vital role in remote procedure call (RPC) systems. Typically, RPC
servers are multithreaded. When a server receives a message, it services the message
using a separate thread. This allows the server to service several concurrent requests.
Finally, many operating system kernels are now multithreaded; several threads operate in
the kernel, and each thread performs a specific task, such as managing devices or
interrupt handling.
Benefits
2. Resource sharing. By default, threads share the memory and the resources of the
process to which they belong.
3. Economy. Allocating memory and resources for process creation is costly. Because
threads share resources of the process to which they belong, it is more economical to
create and context-switch threads. In Solaris, for example, creating a process is about 30
times slower than is creating a thread, and context switching is about five times slower.
Support for threads may be provided either at the user level, for user threads, or by the
kernel, for kernel threads.
User threads are supported above the kernel and are managed without kernel support,
whereas kernel threads are supported and managed directly by the operating system.
3. Many-to-Many Model
• Allows many user level threads to be mapped to
many kernel threads
•Allows the operating system to create a sufficient
number of kernel threads
Examples
Solaris prior to version 9, Windows with the
ThreadFiber package.
CPU Scheduling
CPU-scheduling decisions may take place under the following four circumstances:
1. When a process switches from the running state to the waiting state
2. When a process switches from the running state to the ready state
3. When a process switches from the waiting state to the ready state
4. When a process terminates.
Under non preemptive scheduling, once the CPU has been allocated to a process, the
process keeps the CPU until it releases the CPU either by terminating or by switching to
the waiting state.
Dispatcher
The dispatcher is the module that gives control of the CPU to the process selected
by the short-term scheduler. This function involves the following:
• Switching context
• Switching to user mode
• Jumping to the proper location in the user program to restart that program
The dispatcher should be as fast as possible, since it is invoked during every process
switch. The time it takes for the dispatcher to stop one process and start another
running is known as the dispatch latency.
Scheduling Criteria
• Throughput. The number of processes that are completed per time unit, called
throughput.
• Turnaround time. The interval from the time of submission of a process to the time
of completion is the turnaround time. Turnaround time is the sum of the periods spent
waiting to get into memory, waiting in the ready queue, executing on the CPU, and
doing I/O.
• Waiting time. The amount of time that a process spends waiting in the ready queue.
• Response time. the time from the submission of a request until the first response is
produced. This measure, called response time.
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.
1. First-Come, First-Served Scheduling
2. Shortest-Jab-First Scheduling
3. Priority Scheduling
4. Round-Robin Scheduling
5. Multilevel Queue Scheduling
6. Multilevel Feedback-Queue Scheduling
First-Come, First-Served Scheduling
The implementation of the FCFS policy is easily managed with a FIFO queue. When a
process enters the ready queue, its PCB is linked onto the tail of the queue. When the
CPU is free, it is allocated to the process at the head of the queue. The running process
is then removed from the queue.
The code for FCFS scheduling is simple to write and understand. The average waiting
time under the FCFS policy, however, is often quite long.
Consider the following set of processes that arrive at time 0, with the length of the CPU
burst given in milliseconds:
If the processes arrive in the order P2, P3, P1,however, the results will be as shown in
the following Gantt chart:
P 2
P 3
P 1
0 3 6 30
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.
Eventually, 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. At this point, the CPU sits idle. The CPU-bound process will then
move back to the ready queue and be allocated the CPU. Again, all the I/O processes
end up waiting in the ready queue until the CPU-bound process is done. There is a
convoy effect as all the other processes wait for the one big process to get off the CPU.
This effect results in lower CPU and device utilization than might be possible if the
shorter processes were allowed to go first.
The FCFS scheduling algorithm is nonpreemptive. 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.
As an example of SJF scheduling, consider the following set of processes, with the length
of the CPU burst given in milliseconds:
P 4
P 1
P3 P2
0 3 9 16 24
Shortest-Jab-First Scheduling
The waiting time is 3 milliseconds for process PI, 16 milliseconds for process
P2, 9 milliseconds for process P3, and 0 milliseconds for process P4 . Thus,
By comparison, if we were using the FCFS scheduling scheme, the average waiting time
would be 10.25 milliseconds.
The SJF scheduling algorithm is provably optimal, in that it gives the minimum average
waiting time for a given set of processes.
Although the SJF algorithm is optimal, it cam10t be implemented at the level of short-
term CPU scheduling. There is no way to know the length of the next CPU burst.
As an example, consider the following four processes, with the length of the CPU burst
given in milliseconds:
Shortest-Jab-First Scheduling
• Now we add the concepts of varying arrival times and preemption to the analysis
ProcessA arri Arrival TimeT Burst Time
P1 0 8
P2 1 4
P3 2 9
P4 3 5
• Preemptive SJF Gantt Chart
P 1
P 2
P4 P1 P3
0 1 5 10 17 26
An SJF algorithm is simply a priority algorithm where the priority (p) is the inverse of
the (predicted) next CPU burst. The larger the CPU burst, the lower the priority, and
vice versa.
Aging is a technique of gradually increasing the priority of processes that wait in the
system for a long time.
Priority Scheduling
A small unit of time, called a time quantum or time slice, is defined. A time quantum
is generally from 10 to 100 milliseconds.
The ready queue is treated as a circular queue. The CPU scheduler goes around the
ready queue, allocating the CPU to each process for a time interval of up to 1
time quantum.
If the process may have a CPU burst of less than 1 time quantum. In this case, the
process itself will release the CPU voluntarily.
Otherwise, if the CPU burst of the currently running process is longer than 1 time
quantum, the timer will go off . the process will be put at the tail of the ready queue.
The CPU scheduler will then select the next process in the ready queue.
Round Robin Scheduling
• Three queues:
– Q0 – RR with time quantum 8 milliseconds
– Q1 – RR time quantum 16 milliseconds
– Q2 – FCFS
• Scheduling
– A new job enters queue Q0 which is served
FCFS
• When it gains CPU, job receives 8
milliseconds
• If it does not finish in 8 milliseconds,
job is moved to queue Q1
– At Q1 job is again served FCFS and receives
16 additional milliseconds
• If it still does not complete, it is
preempted and moved to queue Q2