Operating Systems
================ Start Lecture #7 ================
Remark: Discuss the diagram above (before the
examples) explaining why can't tell safety without initial claims.
Remark: Lab 3 (banker) assigned.
It is due in 2 weeks.
Remark: An unsafe state is not
necessarily a deadlocked state.
Indeed, if one gets lucky all processes in an unsafe state may
terminate successfully.
A safe state means that the manager can
guarantee that no deadlock will occur.
3.5.3: The Banker's Algorithm (Dijkstra) for a Single Resource
The algorithm is simple: Stay in safe states. Initially, we
assume all the processes are present before execution begins and that
all initial claims are given before execution begins.
We will relax these assumptions very soon.
- Before execution begins, check that the system is safe.
That is, check that no process claims more than the manager has).
If not, then the offending process is trying to claim more of
some resource than exist in
the system has and hence cannot be guaranteed to complete even if
run by itself.
You might say that it can become deadlocked all by itself.
- When the manager receives a request, it pretends to grant
it and checks if the resulting state is safe.
If it is safe the request is granted, if not the process is
blocked.
- When a resource is returned, the manager (politely thanks the
process and then) checks to see if “the first” pending
requests can be granted (i.e., if the result would now be
safe).
If so the request is granted.
Whether or not the request was granted, the manager checks to see if
the next pending request can be granted, etc..
Homework: 13.
3.5.4: The Banker's Algorithm for Multiple Resources
At a high level the algorithm is identical: Stay in safe states.
- What is a safe state?
- The same definition (if processes are run in a certain
order they will all terminate).
-
Checking for safety is the same idea as above.
The difference is that to tell if there are enough free resources
for a processes to terminate, the manager must check that
for all resources, the number of free units is at
least equal to the max additional need of the process.
Limitations of the banker's algorithm
- Often users don't know the maximum requests a process will make.
They can estimate conservatively (i.e., use big numbers for the claim)
but then the manager becomes very conservative.
- New processes arriving cause a problem (but not so bad as
Tanenbaum suggests).
- The process's claim must be less than the total number of
units of the resource in the system. If not, the process is not
accepted by the manager.
- Since the state without the new process is safe, so is the
state with the new process! Just use the order you had originally
and put the new process at the end.
- Insuring fairness (starvation freedom) needs a little more
work, but isn't too hard either (once an hour stop taking new
processes until all current processes finish).
- A resource can become unavailable (e.g., a tape drive might
break).
This can result in an unsafe state.
Homework: 21, 27, and 20. There is an interesting
typo in 20: A has claimed 3 units of resource 5,
but there are only 2 units in the entire system.
Change the problem by having B both claim and be allocated 1 unit of
resource 5.
3.7: Other Issues
3.7.1: Two-phase locking
This is covered (MUCH better) in a database text. We will skip it.
3.7.2: Non-resource deadlocks
You can get deadlock from semaphores as well as resources. This is
trivial. Semaphores can be considered resources. P(S) is request S
and V(S) is release S. The manager is the module implementing P and
V. When the manager returns from P(S), it has granted the resource S.
3.7.3: Starvation
As usual FCFS is a good cure. Often this is done by priority aging
and picking the highest priority process to get the resource. Also
can periodically stop accepting new processes until all old ones
get their resources.
3.8: Research on Deadlocks
Skipped.
3.9: Summary
Read.
Chapter 4: Memory Management
Also called storage management or
space management.
Memory management must deal with the storage
hierarchy present in modern machines.
-
Registers, cache, central memory, disk, tape (backup)
-
Move data from level to level of the hierarchy.
-
How should we decide when to move data up to a higher level?
- Fetch on demand (e.g. demand paging, which is dominant now).
- Prefetch
- Read-ahead for file I/O.
- Large cache lines and pages.
- Extreme example. Entire job present whenever running.
We will see in the next few weeks that there are three independent
decision:
-
Segmentation (or no segmentation)
-
Paging (or no paging)
-
Fetch on demand (or no fetching on demand)
Memory management implements address translation.
-
Convert virtual addresses to physical addresses
- Also called logical to real address translation.
- A virtual address is the address expressed in
the program.
- A physical address is the address understood
by the computer hardware.
-
The translation from virtual to physical addresses is performed by
the Memory Management Unit or (MMU).
-
Another example of address translation is the conversion of
relative addresses to absolute addresses
by the linker.
-
The translation might be trivial (e.g., the identity) but not in a modern
general purpose OS.
-
The translation might be difficult (i.e., slow).
- Often includes addition/shifts/mask--not too bad.
- Often includes memory references.
- VERY serious.
- Solution is to cache translations in a Translation
Lookaside Buffer (TLB). Sometimes called a
translation buffer (TB).
Homework: 6.
When is address translation performed?
-
At compile time
- Compiler generates physical addresses.
- Requires knowledge of where the compilation unit will be loaded.
- No linker.
- Loader is trivial.
- Primitive.
- Rarely used (MSDOS .COM files).
-
At link-edit time (the “linker lab”)
- Compiler
-
Generates relative (a.k.a. relocatable) addresses for each
compilation unit.
-
References external addresses.
- Linkage editor
- Converts the relocatable addr to absolute.
- Resolves external references.
-
Misnamed ld by unix.
-
Must also converts virtual to physical addresses by
knowing where the linked program will be loaded. Linker
lab “does” this, but it is trivial since we
assume the linked program will be loaded at 0.
-
Loader is still trivial.
-
Hardware requirements are small.
-
A program can be loaded only where specified and
cannot move once loaded.
-
Not used much any more.
-
At load time
-
Similar to at link-edit time, but do not fix
the starting address.
-
Program can be loaded anywhere.
-
Program can move but cannot be split.
-
Need modest hardware: base/limit registers.
-
Loader sets the base/limit registers.
-
No longer common.
-
At execution time
- Addresses translated dynamically during execution.
- Hardware needed to perform the virtual to physical address
translation quickly.
- Currently dominates.
- Much more information later.
Extensions
-
Dynamic Loading
- When executing a call, check if module is loaded.
- If not loaded, call linking loader to load it and update
tables.
- Slows down calls (indirection) unless you rewrite code dynamically.
- Not used much.
-
Dynamic Linking
- The traditional linking described above is today often called
static linking.
- With dynamic linking, frequently used routines are not linked
into the program. Instead, just a stub is linked.
- When the routine is called, the stub checks to see if the
real routine is loaded (it may have been loaded by
another program).
- If not loaded, load it.
- If already loaded, share it. This needs some OS
help so that different jobs sharing the library don't
overwrite each other's private memory.
- Advantages of dynamic linking.
- Saves space: Routine only in memory once even when used
many times.
- Bug fix to dynamically linked library fixes all applications
that use that library, without having to
relink the application.
- Disadvantages of dynamic linking.
- New bugs in dynamically linked library infect all
applications.
- Applications “change” even when they haven't changed.
Note: I will place ** before each memory management
scheme.
4.1: Basic Memory Management (Without Swapping or Paging)
Entire process remains in memory from start to finish and does not move.
The sum of the memory requirements of all jobs in the system cannot
exceed the size of physical memory.
** 4.1.1: Monoprogramming without swapping or paging (Single User)
The “good old days” when everything was easy.
-
No address translation done by the OS (i.e., address translation is
not performed dynamically during execution).
-
Either reload the OS for each job (or don't have an OS, which is almost
the same), or protect the OS from the job.
- One way to protect (part of) the OS is to have it in ROM.
- Of course, must have the OS (read-write) data in ram.
- Can have a separate OS address space only accessible in
supervisor mode.
- Might just put some drivers in ROM (BIOS).
-
The user employs overlays if the memory needed
by a job exceeds the size of physical memory.
- Programmer breaks program into pieces.
- A “root” piece is always memory resident.
- The root contains calls to load and unload various pieces.
- Programmer's responsibility to ensure that a piece is already
loaded when it is called.
- No longer used, but we couldn't have gotten to the moon in the
60s without it (I think).
- Overlays have been replaced by dynamic address translation and
other features (e.g., demand paging) that have the system support
logical address sizes greater than physical address sizes.
- Fred Brooks (leader of IBM's OS/360 project and author of “The
mythical man month”) remarked that the OS/360 linkage editor was
terrific, especially in its support for overlays, but by the time
it came out, overlays were no longer used.