Concurrency and Operating Systems
|
An operating system can have a very simple design,
if the computer it controls
has just a single user running a single process
the whole of which is small enough to fit into memory running
on a single processor because many design problems are avoided.
The system, however, is far too simplistic to be useful, is
extremely wasteful of resources and is operating far below potential.
A operation system can be:
- multitasking or
multiprogramming
- appear to be running several processes at once,
-
multiuser - have
several users using it at the same time,
- multiprocessor capable -
able to handle multiple CPU systems,
and together with hardware can also support:
-
virtual memory addressing
- the address space (apparently accessible memory)
of a process does not need to be identical to the physical address space.
The virtual address space can be much larger than the physical space.
Each process can have the same view of memory, for example, its program
code is at (the same) very low virtual addresses even though physically
this would be possible for at most one process.
These features can be achieved by giving each process a slice of time
on a processor and a slice of memory for running and allocating
resources as necessary.
A scheduler allocates time.
It decides when a process has used up
enough time and should be forced to relinquish a processor. Often processes
are forced off a processor before their alloted time is up because they
are doing I/O and have to wait for I/O to complete - devices are
typically very slow compared to the CPU. Processes can also be forced
off as a result of signals or because higher priority processes want time.
A pager moves pages (contents of blocks of memory)
in and out of memory to disk so that a
process can appear to have a large address space, independent of
all other processes but also shared where desired, and much
larger than actual memory.
A swapper moves processes to and from memory,
by moving process pages and
process data that the kernel has for the process.
Concurrency cannot be avoided because:
-
Users are concurrent - a person can handle several tasks at once
(have you every listened to music while doing other work
and heard the phone ring?) and expects
the same from a computer.
- Multiprocessors are becoming more prevalent.
The Internet is perhaps a huge multiprocessor.
- A distributed system (client/server system) is naturally concurrent.
- A windowing system is naturally concurrent.
- I/O is often slow because it involves slow devices such as disks,
printers; many network operations are essentially (slow) I/O operations.
When doing I/O it is helpful to handle the I/O concurrently with other work.
Whenever concurrency is involved certain issues, discussed below, arise.
An understanding of these issues is important when:
- writing an operating system.
- when interacting with the kernel, for example, when performing I/O.
- when generating multiple processes, for example, with forks and
pipelines.
- when using multiple threads.
Concurrency issues (expressed using processes):
- Atomic.
An operation is atomic if the steps are done as a unit.
Operations that are not atomic, but interruptible and done by multiple
processes can cause problems. For example,
an lseek followed by a write
is not atomic. A process is likely to lose its time quantum between the
lseek (a slow operation if the distance seeked is large!)
and the write. If another process has the
file open and does a write then the result is not what is intended.
- Race conditions. A race condition occurs
if the outcome depends on which of several
processes gets to a point first. For example,
fork( )
can generate a
race condition if the result depends on whether the parent or
the child process runs first.
Other race conditions can occur if two processes are
updating a global variable.
- Blocking and
starvation.
While neither of these problems is unique to concurrent processes,
their effects must be carefully considered.
Processes can block waiting for resources. A process could be blocked
for a long period of time waiting for input from a terminal.
If the process is required to periodically update some data,
this would be very undesirable. Starvation
occurs when a process does not
obtain sufficient CPU time to make meaniful progress.
- Deadlock.
Deadlock occurs when two processes are blocked in
such a way that neither can proceed. The typical occurrence is where
two processes need two non-shareable resources to proceed but one
process has acquired one resource and the other has acquired the other
resource. Acquiring resources in a specific order can resolve
some deadlocks.
Various kinds of locks can be used to avoid these problems.
Last update: 2001 April 5