Memory Management
Prerequisite Knowledge
This lecture builds on the following concepts from earlier lectures. If any feel unfamiliar, review the linked notes before proceeding.
Previously Covered in This Subject
- Memory management fundamentals — covered in Lecture 1 (bringing programs into memory; tracking, allocating, and deallocating)
- Dual-mode operation: user mode and kernel mode — covered in Lecture 1
- Process creation and termination — covered in Lecture 3 (fork and the process lifecycle)
- Swapping and the medium-term scheduler — covered in Lecture 3
- Threads and multithreading — covered in Lecture 4 (threads share process memory)
- FCFS scheduling and the convoy effect — covered in Lecture 5
- Round robin scheduling — covered in Lecture 6
- Process synchronization: semaphores, monitors, and Peterson's solution — covered in Lectures 7 and 8
- Deadlocks: the four necessary conditions — covered in Lecture 9
11.1 Memory Management: Module Overview
11.1.1 The Three Levels of Memory
Hook: Every program you run must live somewhere while it executes — but the machine's fast storage is tiny and its big storage is slow. How does the operating system decide where each process goes, and what happens when everything does not fit at once? That is the question the whole memory management module answers.
Memory exists at three broad levels, each further from the processor and each with a different price:
- Main memory — the working space where processes run. It is fast, but it is also expensive and small, and it is volatile: everything in it disappears when the power goes off.
- Secondary storage (for example, a hard disk) — the parking lot that holds the programs that are waiting. It is cheap, non-volatile, and large, but much slower than main memory.
- Tertiary storage — sits even further down the hierarchy (for example, magnetic tape or optical media). It is the slowest and cheapest level, used for archiving rather than for running programs.
The whole memory management module asks one central question: with a main memory and a secondary storage available, how do we place processes into memory?
The answer is rarely "load everything and leave it there". Memory is finite, and the set of processes that want to run at any moment usually outgrows it:
- If the memory is not enough to store everything, we have to swap the excess to the secondary storage — the process's image is written out to the disk while it waits.
- When a process is needed again, it is brought back into the main memory.
All of this — the placement of processes into memory, the swapping out of idle ones, the bringing back of needed ones — is managed by the operating system, not by the programmer. The programmer writes the program and starts it; the operating system silently decides where in memory it actually sits.
Exam note: the professor opened the session by stressing that this is a very important module — one of the core topics of the course. The techniques of memory management are covered in this session, and the problems connected with these techniques will be solved in the next session. Whatever does not fit in this session continues there. Do not treat memory management as a side topic: it carries its own problem-solving session, which tells you how heavily it can appear in exams.
Real-world: the three levels you meet here are the coarse-grained view of a whole memory hierarchy. Real systems add even faster layers on top (registers inside the CPU, cache memory between the CPU and main memory) precisely because main memory is already too slow for the processor. Modern operating systems automate the main-memory ↔ secondary-storage traffic with a mechanism called virtual memory — the direct descendant of the swapping idea described above, and the destination this module is heading toward.
11.1.2 What the Operating System Must Provide
Managing memory is not a one-off job. Before we can say memory is being managed well, the operating system has to satisfy several requirements at once — the professor listed five, and each one gets its own treatment below:
- Relocation — the ability to place and run a process at different locations in memory at different times.
- Protection — keeping each process safe from the others while it resides in memory.
- Sharing — allowing several processes to access the same portion of memory when that is wanted.
- Logical organization — structuring how the program's modules are arranged in memory.
- Physical organization — deciding how the program is placed into the actual physical memory hardware.
Each of these is very, very important for memory management. They are also connected: relocation and protection together build the base-and-limit-register mechanism of the next sections, sharing ties memory management back to process synchronization, and logical and physical organization define the two address spaces that the memory management unit works with.
Recap: memory spans three levels (main, secondary, tertiary); the operating system's job is placing processes, swapping out what does not fit, and bringing it back. Five requirements define "good" memory management: relocation, protection, sharing, logical organization, and physical organization. The rest of this module examines each one in turn — and the section numbering below is exactly that list.
11.2 The Five Requirements of Memory Management
11.2.1 The List of Requirements
Hook: A process sitting in memory can be moved, corrupted, or duplicated without its knowledge. What does the operating system have to control so that a process is safe, correctly placed, and able to cooperate with others? The answer is the five requirements below.
The five requirements that memory management has to satisfy are:
- Relocation — the ability to place and run a process at different locations in memory at different times. The location is not fixed forever: a process may be loaded, swapped out, and later reloaded somewhere else, and it must still run correctly.
- Protection — keeping each process safe from the others while it resides in memory. One process must not be able to read or overwrite another process's memory — or the operating system's own memory.
- Sharing — allowing several processes to access the same portion of memory when that is wanted. Protection and sharing sound contradictory, but both are needed: some regions are private, and some (shared code, shared data) are deliberately accessible to several processes at once.
- Logical organization — structuring how the program's modules are arranged in memory. Programs are not one flat blob; they are built from separately written and separately compiled modules, and memory management must respect that structure.
- Physical organization — deciding how the program is placed into the actual physical memory hardware. The memory hardware has its own layout, and the system has to decide how program pieces map onto it.
11.2.2 Why the List Matters
These five are not separate exam points to memorize in isolation — they interact, and the professor presented them in the order the rest of the module follows:
- Relocation and protection together give us the base and limit register mechanism. Relocation asks "where may the process sit, and how do we keep its addresses working when it moves?"; protection asks "how do we stop it from touching anything outside its region?" The answer to both fits in two registers, as the next section shows.
- Sharing connects memory management to process synchronization, which was studied earlier. The synchronization module already dealt with variables and files accessed by multiple processes; here the memory side of that story is completed — the memory manager must make the shared portion simultaneously accessible to the processes.
- Logical and physical organization set up the address spaces that the memory management unit works with. Logical organization produces the addresses the program sees; physical organization decides what those addresses mean on the real hardware. Bridging the two is the memory management unit (MMU).
Recap: the five requirements are relocation, protection, sharing, logical organization, and physical organization. The rest of this module builds on exactly these five — the sections on base and limit registers, on address spaces, on fixed and dynamic partitioning, and on fragmentation are each a working out of one (or two) of these requirements.
11.3 Relocation and Address Binding
11.3.1 What Relocation Means
Hook: Imagine your office moves to a new floor in the building every week, yet your desk phone still works and everyone can still find you. That is what relocation does for a process: the operating system moves it around memory, and the process keeps running correctly from wherever it lands.
A program sitting in secondary storage has to be brought into main memory before it can be executed. There may be many processes waiting on the disk to be brought in, and the operating system has to manage both the order in which they come and the placement — where each one lands in memory. The programmer does not know any of this: the programmer simply writes the program, stores it, and later starts executing it without worrying about where it physically sits or when it is loaded.
Here is the key situation the professor built up:
- A process P1 is brought from the hard disk into main memory and starts running.
- If P1 is idle for some time, it is swapped back to secondary storage — moved out to make room or simply because it is not needed right now.
- Later, when P1 is required again, it is brought back into main memory — but not necessarily at the same location. The location differs from the first load.
That is called relocation: the system loads the program or process at a different location in memory and executes it from there.
Because the location is not fixed, no one — including the operating system — knows in advance where the process will sit. When a process is brought in, the operating system first has to locate the process, then take its address and translate it into a physical memory address — the actual memory location where the process will be placed. Only then can execution continue.
Pitfall: it is tempting to think "the process starts at address 0, so addresses are fixed". Relocation breaks that assumption: the process's own addresses (as the program sees them) are not the addresses where the data actually lives in hardware. The step in between — the translation — is exactly the subject of the next subsection.
11.3.2 Address Binding: Mapping One Address Space to Another
This translation from one address space to another address space is called address binding. Bringing a process from the disk into main memory is one example of the mapping; the same idea applies to data as well, since data may also reside at different places and has to be brought in for execution.
The standard reference treatment describes the journey of an address in three steps (Silberschatz, Operating System Concepts, Ch. 8):
- In the source program, addresses are purely symbolic (names like
count). - The compiler binds these symbolic addresses to relocatable addresses (for example, "14 bytes from the beginning of this module").
- The linkage editor or loader binds the relocatable addresses to absolute addresses (such as 74014).
Every one of these bindings is a mapping from one address space to another — exactly the professor's definition. The professor then notes that address binding takes place at three different stages: compile time, load time, or execution time. Compile time and execution time are terms you would have come across while doing any programming language work.
11.3.3 Compile-Time Binding
At compile time, everything about the program is known in advance. The memory location where the code will sit is also known, so the compiler generates absolute code — code with fixed, absolute addresses baked in.
The problem: if you make changes to the existing code, you have to compile it again (the professor's phrase was "decompile", meaning recompile), and the location of the code changes. Suppose the code originally started at address 1000. After the change and the recompile, it may start at a different location, say 2000. So compile-time binding produces code that is fixed to one specific place in memory — moving it would break every absolute address inside it.
Worked example — the recompile trap. A program is compiled when the system knows it will run at address 1000, so the compiler writes the absolute address 1000 into every instruction that references the program's start. Later the starting location changes to 2000. The stored binary still says 1000, so it can no longer be loaded correctly — the only fix is to recompile the code, generating a fresh binary with 2000 everywhere. This is why compile-time binding is only usable when the process's future location is known at compile time (for example, the MS-DOS .COM-format programs mentioned in the reference text).
11.3.4 Load-Time Binding
At load time, the compiler generates relocatable code instead of absolute code. Relocatable means the code is flexible — it can be placed anywhere in memory when it is executed. The final binding of the address is not done at compile time; the code stays in relocatable form so that the starting address may change whenever the program is reloaded into memory for execution. The actual fixing-up of the addresses happens at load time, when the loader places the code at some chosen starting address and patches the addresses accordingly.
Load time sits in between compile time and execution time. If the starting address changes between two runs, you only need to reload the code with the new start address — no recompilation is needed, unlike compile-time binding.
11.3.5 Execution-Time Binding
At execution time, the binding is delayed even further — it waits until the process is actually being executed. The process is moved into memory and executes, and the binding is done only during that execution. This is the most flexible stage: the process can even be moved from one memory segment to another while it is running, and every address still works, because the translation happens at the moment of each memory reference.
This stage needs hardware support to perform the mapping, because the base address and the limit registers can change at any moment. The base and limit registers will be examined in detail next — they are the hardware that makes execution-time binding possible.
Comparison — when to pick which binding:
| Binding stage | Code produced | What happens if the start address changes | Hardware needed |
|---|---|---|---|
| Compile time | Absolute code | Recompile ("decompile") — expensive | None |
| Load time | Relocatable code | Reload with the new start address | None |
| Execution time | Relocatable code | Nothing — addresses translate on every reference | Base/limit registers, MMU |
The professor's rule of thumb: compile-time binding is rigid and simple; load-time binding is a middle step; execution-time binding is what general-purpose operating systems use, because it is the only one that survives a process being swapped out and reloaded at a fresh location — the exact relocation scenario of section 11.3.1.
Recap + bridge: relocation is the OS placing a process at different memory locations at different times; address binding is the translation of addresses between spaces, done at compile time (absolute code, recompile needed), load time (relocatable code, reload fixes it), or execution time (hardware mapping on the fly). Execution-time binding needs the base and limit registers — which are exactly the next topic, protection.
Real-world: execution-time binding is not just a textbook idea. Modern systems randomize where a process is loaded on every run (address space layout randomization, ASLR) so that attacks cannot predict code locations — a modern security feature that is nothing but relocation in action. Dynamic linkers, which resolve shared-library addresses at load time, are load-time binding; the base/limit register machinery below is the execution-time binding mechanism.
11.4 Protection with Base and Limit Registers
11.4.1 The Idea: Every Process Must Be Safe
Hook: Your process's memory is its private room in a shared building. What stops the neighbour from walking in and rewriting your files? In memory management, the answer is hardware-enforced room boundaries: the base and limit registers.
Protection is the second requirement of memory management. A program or process, wherever it is present in memory, should be safe — it should not get corrupted (the professor's phrasing was "it should not get corrected", meaning modified or overwritten by another process). Every process gets a separate space in memory, and the point of that separation is only safety and security.
Protection is provided with the help of two registers: the base register and the limit register. For each and every process, the system must know its base and its limit. When the operating system switches to a process, it loads that process's two values into the registers; every memory reference the process makes is then checked against them by hardware.
11.4.2 Base, Limit, and the Size of the Process
The base register always holds the starting address of the process. It is the smallest legal physical memory address for that process — and it is called the smallest precisely because it is the starting address; anything below the base belongs to another process (or to the operating system). The limit register specifies the size of the process's address range. If we add the limit to the existing base, we get the extent of the address range the process occupies — the professor writes it as the size of the process:
The base can change at any time because of the different types of binding we saw with relocation, so the system always checks what base plus limit is currently giving. If the process is relocated (moved), only the base value changes in the register — the limit stays the same, because the process did not change size.
Scope / notation: the standard treatment in the reference text (Operating System Concepts, §8.1.1) defines the base register as "the smallest legal physical memory address" and the limit register as "the size of the range". So in textbook notation the range holds exactly limit addresses, and the last legal address is base + limit − 1: for base 300040 and limit 120900, the text says the program may access 300040 through 420939 (inclusive). The professor's form base + limit is the top boundary of the range (420940 in that example — one past the last legal byte). Both describe the same fence; the exam follows the professor's form, and the check below uses it.
11.4.3 The Address-Checking Flow
The CPU generates an address; this is called a logical address, because it is the address as seen from the user's point of view — whatever the CPU generates is a logical address. This address is fed to the hardware and checked against the base: it should not be less than the base. Only if that condition is satisfied does the check move to the next step. Otherwise, a trap is made to the system so the error can be found out.
Next, the address is checked against base plus limit: the address must stay within this limit, it should not go beyond it. If that also passes, the physical address is formed and given to the memory, where the process is placed for execution. So the legal range for an address is:
This is exactly the mechanism in the reference text (§8.1.1): the base register holds the smallest legal physical memory address, the limit register specifies the size of the range, and the CPU hardware compares every address generated in user mode with the registers. Any attempt to access operating-system memory or another user's memory results in a trap to the operating system, which treats the attempt as a fatal error.
The professor's summary of the mechanism: "if that is the case, the space plus limit forms the physical address". Working out that phrase with the relocation-register idea from the Physical Organization section: the process's logical space starts at 0, so the physical address is formed by adding the base (the "space" start, which the professor also calls the relocatable address R) to the logical address:
The physical address is then handed to the memory for execution.
Worked example — checking addresses against the fence. Take a process whose base register holds 300040 and whose limit register holds 120900. Per the professor's form, the legal range is:
- The process references address 300040: it equals the base, passes both checks, and is legal (its own first byte).
- The process references address 420939: below base + limit, legal — the last byte of its data area under the strict reading.
- The process references address 300039: it is below the base — that memory belongs to the previous process or the operating system. The hardware traps to the OS; the attempt fails.
- The process references address 420941: it exceeds base + limit — also outside the fence; again a trap.
Every address the process generates, for instructions or for data, runs this same pair of comparisons before the memory is touched. The one-sentence sense-check: the fence is the interval between the starting address (base) and the starting address plus the range size (base + limit); anything outside it never reaches memory.
11.4.4 Hardware Support and Privileged Instructions
Relocation and the limit checks need hardware support — the comparisons happen on every single memory reference, so they cannot be done by software after the fact. Certain instructions are privileged instructions — they exist only to load and read the base and limit registers, and only the operating system can execute them. The reference text confirms: the base and limit registers can be loaded only by the operating system, using a special privileged instruction; since privileged instructions can be executed only in kernel mode, and only the operating system executes in kernel mode, user programs can never change the registers' contents.
The operating system has access to both the system space and the user space: the operating system space cannot be used by user programs, but the operating system can use the system space and also touch the user space when needed — it must load user programs into user memory, dump them on error, and pass parameters to system calls.
Pitfalls:
- "Any address below base belongs to someone else" — do not forget the limit side. A process may not touch addresses above base + limit either; that region belongs to a later process. Both checks are mandatory.
- Confusing base with the process's size. The base is a starting address, not an amount of memory. The professor's intuition: the base is the smallest legal physical address because it is the starting address.
- Assuming the user program can change its own registers. Only the OS, via a privileged instruction in kernel mode, may load or read the base and limit registers. Otherwise any process could widen its own fence and protection would be worthless.
- Mixing up the two roles of the registers in the flow. First compare against base (lower bound), then against base + limit (upper bound), and only then form the physical address — the professor's checking order is exactly this sequence.
Recap + bridge: protection uses two registers per process — base (smallest legal address, the starting address) and limit (size of the range). Every logical address must satisfy base ≤ address ≤ base + limit; violations trap to the OS; the physical address is base + logical. Only privileged OS instructions can load these registers. This mechanism protects the process's private memory — but next we see what happens when processes are supposed to share: sharing is the third requirement.
Real-world: base-and-limit protection was the classic hardware protection scheme of early operating systems, and the same idea survives in modern hardware in disguise — Intel x86 segmentation registers bound a program to a region of memory, and every modern memory management unit (MMU) enforces the same "legal range per process" idea at much finer granularity. The check flow above is also the conceptual ancestor of the bounds checks that make modern sandboxes and web browsers safe.
11.5 Sharing Memory Between Processes
11.5.1 The Requirement
Hook: We just built fences to keep every process out of everyone else's memory — and now we want some memory that several processes are deliberately allowed to touch. Protection says "stay out"; sharing says "come in". How do the two live together?
The name says it: sharing means several processes try to access the same portion of memory. We already met this idea in process synchronization, where a particular variable, or a particular code, or a file is shared by multiple processes. The synchronization itself is handled separately — that was the synchronization module. But managing the memory so that such sharing is possible is one of the requirements of memory management: it allows several processes to access the same portion of memory.
There are problems when several processes access the same portion, as we saw in synchronization — two processes reading and writing the same variable can interleave in harmful ways. One simple-looking escape is to give every process a separate copy of the shared data. But a separate copy is an overhead: it occupies extra space in memory, and that space is not free. If instead we go for sharing, we have to follow some protocols to keep it safe (the locks, semaphores, and monitors of the synchronization module). Both costs are real, and the choice between them is exactly what the memory manager has to reason about.
Comparison — separate copies versus sharing:
| Option | Space cost | Safety cost | Used when |
|---|---|---|---|
| Separate copy per process | Extra memory for every extra process — not free | No interference between processes; no protocol needed | Small data, few processes |
| Shared memory | One copy serves all | Need synchronization protocols (locks, semaphores, monitors) | Large common code/data, many processes |
End of the comparison, the professor's rule: sharing wins when the shared portion is large or used by many processes (a shared library, a shared buffer); private copies win for small data where protocol overhead would be silly.
11.5.2 Student Questions and Answers: How Sharing Actually Works
A student raised the practical doubt that sharing between threads is easy to imagine, but sharing between whole processes is harder to picture:
Q: Sharing memory between threads is possible — I understand that. But whenever it comes to different processes, how does that happen?
A: It is exactly what we saw in process synchronization. If only two processes are there, we can use the Peterson solution. If it is hardware-based, we use the synchronization support we saw — the lock — and then semaphores. When a process runs, it is isolated in its own memory; no cross memory accessibility is given to processes. But when sharing is wanted, the shared portion of memory must be brought into the main memory along with the process — or at least the references for the shared memory must be present in the process. Every time the process is executed, it takes the reference from there, transfers control to that particular location, and gets the data. The shared portion has to be there in the main memory; only then can execution of the process take place.
The misconception hiding behind this question: "processes are isolated, so sharing cannot really happen". The resolution: isolation is the default, not an absolute law. The shared portion itself must be resident in main memory, and the process carries only a reference to it. The isolation fence (base/limit protection) is deliberately widened to admit that one shared region; the memory manager sets this up when the process is loaded.
Q: So even when the data is in secondary storage, it has to be brought in?
A: Yes, it has to be brought. The references for the shared memory are in the program, and when we bring it, the address translation and everything else is done by the memory management unit. As a user we need not worry about that — we just mention what is to be shared through the particular process, and that reference alone is enough.
This second question is a different confusion point, and the professor's answer completes the picture: the user never moves bytes around by hand. The program declares what it wants to share; the operating system and the memory management unit arrange the physical placement and the address translation. "The reference alone is enough" — the process points at the shared region and the MMU resolves the pointing at execution time.
Recap + bridge: sharing is the third requirement: several processes access the same portion of memory, with the shared portion resident in main memory and references carried in the programs. The memory manager sets the shared region up; the synchronization module supplies the protocols that make concurrent access safe. This completes the story of sharing — next comes how programs are structured in memory: logical organization.
Real-world: this is precisely how threads in a real program share global variables (one copy of the data in the process's memory, every thread referencing it), and how memory-mapped files let different processes read the same file region without copying it. It is also exactly how shared libraries work: one copy of a DLL or a .so file sits in main memory, and dozens of processes map their references onto that single copy — saving the memory that separate copies would waste.
11.6 Logical Organization of Memory
11.6.1 Programs as Modules
Hook: A large enterprise system is not one giant file written by one person — it is dozens of modules written by different teams. Memory has to be organized so that such programs can actually live in it, module by module. That is logical organization.
Memory can be organized either logically or physically. Logical organization starts from how programs are actually written. A program is usually written as different modules, and each module is written and compiled separately, then integrated into the whole. That is a real advantage when you think of a very large program that runs in an organization or an enterprise — not a small program, but the kind of system where teams build modules and compile them independently.
Each module is self-contained enough to be compiled on its own, and the pieces are combined later. This separates the work: team A compiles the payroll module while team B compiles the inventory module, and neither waits for the other's code to exist.
11.6.2 Protection Modes and Sharing of Modules
All modules do not have to be executable by everyone. Some modules get protection in the form of modes: read only, or execute only. The protection modes are a natural extension of the base-and-limit idea: not only where a module lives in memory, but also what may be done with it — a read-only module cannot be corrupted by a misbehaving process, an execute-only module cannot be copied out as data.
Some modules might be shared among different processes. When modules are shared among processes, or when a program is divided into modules, we need segmentation: the whole program is divided into different segments, each segment is checked to see whether it is within its limit, and then execution takes place. Segmentation is a separate topic of its own that is covered later. The checks are also done against secondary storage, since segments may live there when not in use.
The reference treatment (Operating Systems: Internals and Design Principles, Ch. 7) describes the same picture: segmentation divides a program into pieces that need not all be contiguous in memory, allows each segment to be protected independently (read-only, execute-only, shared), and keeps segments on secondary storage when they are not in use — a first step toward the virtual memory ideas that come later in the course.
Recap + bridge: logical organization structures memory the way programs are actually written — as separately compiled modules. Modules can be protected (read only, execute only) or shared between processes, and dividing programs into modules/segments with per-segment limits leads to segmentation, covered later. The next section turns to the other half of the pair: physical organization — how the modules land on the real memory hardware.
Real-world: every large enterprise software system is built this way — independent modules compiled separately and linked into one product, with shared libraries holding common code that all processes may read but not modify. The read-only protection on shared libraries is exactly the "read-only module" idea above, enforced by the operating system on every modern platform.
11.7 Physical Organization and Address Spaces
11.7.1 Main Memory versus Secondary Storage
Physically we have two types of memory: main memory and secondary storage. The professor lined up their differences:
- Main memory is much faster than secondary storage, but the cost is high, it is highly volatile (its contents vanish with the power), and its capacity is small.
- Secondary storage is not costly, it is non-volatile, and its capacity is large — but it is far slower.
Why go to secondary storage at all? Because some processes are not needed at all times. Those processes live in secondary memory and are later brought into main memory for execution. The programmer never deals with this memory management — it is done by the memory management unit (MMU) of the operating system. So we have to know what different address spaces exist and how the mapping between them takes place, and that leads into virtual memory.
11.7.2 Logical (Virtual) and Physical Addresses
There are two address spaces:
- The address generated by the CPU is the logical address, otherwise called the virtual address. This is the address the program thinks in terms of — the reference text notes that in the execution-time binding scheme, logical and virtual are used interchangeably.
- The physical address is the one present in the memory unit, the address seen by the memory unit itself — the address sitting in the memory address register (MAR).
The mapping between the virtual address and the physical address is done with the help of hardware — the memory management unit (MMU). The user program always deals with the logical address and never sees the real physical address. The professor's intuition, worth keeping: the user sees only logical addresses; the memory management unit does the mapping. The program can even create a pointer to location 346, store it, and manipulate it — all as the number 346 — and only when the pointer is actually used as a memory address does the hardware relocate it.
11.7.3 The Relocation Register and Dynamic Relocation
The user thinks of the process as running at locations zero to maximum: logical addresses form a range from zero up to some maximum value. For the system, the actual range starts at a base address R, the relocatable address, so the physical range given to a particular process runs from R + 0 up to R + max:
This is the exact formulation of the reference text (§8.1.3): "We now have two different types of addresses: logical addresses (in the range 0 to max) and physical addresses (in the range R + 0 to R + max for a base value R)." The user program generates only logical addresses and thinks the process runs in locations 0 to max; these logical addresses must be mapped to physical addresses before they are used. The base register of the protection scheme is renamed in this context: it is now called the relocation register, and the scheme is called dynamic relocation.
Every time a logical address is generated, the value in the relocation register (R) is added to it, and the result is sent to memory for execution. That addition is done by the memory management unit. This is called dynamic relocation. Whenever a logical address is converted to a physical address, this type of relocation must be done; only then is the process executed in memory.
11.7.4 Worked Example: Adding the Relocation Register
Worked example — a logical address meets the relocation register. The block-diagram version of the story: the CPU generates a logical address — take 346 as the example value. This is fed to the memory management unit, which reads the relocation register, whose value happens to be 14000. The addition:
So the physical address is 14346 — that is the address where the program's byte at logical location 346 actually sits in hardware.
The same arithmetic happens on every single logical address the process issues. Two more steps of the same process:
- Logical address 0 (the very first byte of the program): physical address , the start of the process in memory.
- Logical address 1500: physical address .
Sense-check: every physical address equals the logical address shifted up by the constant R, so the whole process appears in memory as one contiguous block starting at 14000 — exactly what the base-and-limit fence of section 11.4 described from the protection side. This is the reference text's own example: "if the base is at 14000, then an attempt by the user to address location 0 is dynamically relocated to location 14000; an access to location 346 is mapped to location 14346."
Visual intuition: picture a memory strip. The relocation register R pins the process's starting point (14000) on the strip. Every logical address is a distance measured from that pin — the process "thinks" it lives at 0, 1, 2, ..., but the MMU re-anchors every reference to R + 0, R + 1, R + 2, ... . The shape is a simple linear shift: the process's image slides along the memory strip as R changes, without its internal distances changing at all.
Assumptions & scope: this mapping works because the process occupies one contiguous block. If the process's memory were scattered across non-contiguous pieces (as paging and segmentation allow), one register could no longer describe the mapping — each piece would need its own base. That limitation is precisely what pushes memory management on to the more advanced schemes covered later.
Pitfalls:
- The user program never sees physical addresses. A program that "reads" its own addresses is still working with logical addresses; the relocation happens only when the address is used to reach memory.
- Do not mix up which register does what. In the protection scheme it is called the base register; in the dynamic relocation scheme the same register is called the relocation register. Same register, two names — the reference text states this explicitly.
- Forgetting the addition happens on every reference. The MMU adds R on every single memory access, not once at load time — otherwise any process move would break all stored addresses.
Recap + bridge: physical organization pairs main memory (fast, costly, volatile, small) with secondary storage (slow, cheap, non-volatile, large). Two address spaces exist: logical/virtual (generated by the CPU, 0 to max) and physical (seen by the memory unit, R + 0 to R + max). The MMU adds the relocation register R to every logical address — dynamic relocation. The two address spaces we now have are exactly what the partitioning techniques of the next sections must manage.
Real-world: the logical-address view is what lets modern operating systems promise each process "you own the whole address space" while the hardware secretly places the process anywhere. Every desktop and server CPU ships an MMU that performs this addition (and much more) on every memory reference; virtual memory, the topic this module is building toward, is the generalization of exactly this two-address-space picture.
11.8 Fixed Partitioning
11.8.1 The Basic Idea
Hook: The simplest way to share a room between strangers is to cut it into fixed cubicles once and for all. Fixed partitioning does exactly that with memory — and, as we will see, cubicles waste a lot of space.
The first memory management technique is fixed partitioning. The main memory is divided into a fixed number of partitions — static partitions — and that division is generated once, when the system is formed. Whenever a process is brought into main memory, it is placed in one of the partitions. The partition's size may be the same as the process's size, or bigger, or smaller; we will see what happens in each case.
Fixed partitioning is very simple. Depending on the number of partitions, the degree of multiprogramming is set: the degree of multiprogramming means how many programs reside in memory at the same time. If ten partitions exist, at most ten programs can be in memory at a time — the reference text states this limit directly: the degree of multiprogramming is bound by the number of partitions.
Real-world: this exact scheme was used in the IBM OS 360 — multiprogramming with a fixed number of tasks. The reference text names the system: the fixed-partition method was originally used by the IBM OS/360 operating system (called MFT — multiprogramming with a fixed number of tasks); its variable-size relative, MVT, came later. Fixed partitioning is no longer in use today, but it is the right first technique to study because everything after it is a response to its weaknesses.
11.8.2 Worked Example: 8 MB Partitions and a 4 MB Process
Worked example — one process per cubicle. Suppose the whole system is divided into fixed partitions, each carrying 8 MB of space (the reference text's worked example uses exactly this 8-Mbyte partition size: "there may be a program whose length is less than 2 Mbytes; yet it occupies an 8-Mbyte partition whenever it is swapped in"). Whenever a program comes, it is loaded into an available space.
- A program of size 4 MB arrives. It occupies only half of the first available partition; the rest of the partition — 4 MB — is wasted. The partition is 8 MB and cannot be split, so the unused 4 MB sits idle.
- The next program may be 5 MB. The leftover 4 MB in that first partition is not enough, so it cannot go there. The program has to find some other available memory — some other partition with at least 5 MB free.
When the free space left in the system is not contiguous — say all spaces are occupied except a few pieces of 2 MB, 3 MB, or 5 MB — an incoming process may simply not fit into any one of the partitions. That is the core problem of fixed partitioning. When a process does not fit, we have to go for overlaying: place part of the process in one partition and the rest in the next one, piece by piece. Overlaying is a very inefficient use of main memory, and it is the root cause of internal fragmentation.
Sense-check: the numbers work out exactly as the professor stated — a 4 MB process in an 8 MB partition uses half and wastes half; a 5 MB process cannot use the leftover 4 MB because a partition cannot be cut further.
The reference text adds the historical context: with equal-size partitions, a program too big for a partition forces the programmer to design it with overlays so that only a portion of the program need be in main memory at any one time — the programmer's manual technique that memory management later absorbed as a system responsibility.
11.8.3 Internal Fragmentation
What is internal fragmentation? When a space is allocated to a process and some part of that allocated space is left unused, the leftover is internal fragmentation. Example: a process occupies some memory and a 3 MB piece is left out within the allocated space. That 3 MB is internal fragmentation — within the allocated memory, some space is left out, and it cannot be used efficiently.
The textbook definition matches: "This phenomenon, in which there is wasted space internal to a partition due to the fact that the block of data loaded is smaller than the partition, is referred to as internal fragmentation." Note the word internal: the waste happens inside a partition that has been allocated to a process — the space is committed to that process but the process does not use it, and no other process may use it either.
Pitfall: internal fragmentation is not "free space the system can hand out later". The partition is allocated; the leftover is inside the allocation. It is dead space until the process leaves the partition — which is why small programs in large partitions are so wasteful in fixed partitioning.
11.8.4 Unequal Partitions and Queues
Equal partitions are not mandatory. With unequal partitions there is more flexibility — you can take whatever space you want. But then processes must be assigned to partitions, and we need a way to do that. Two options were discussed:
- One queue per partition. For each and every partition, form a separate queue. Whenever a small process comes, it is placed in that partition's queue; the next small process goes into the same queue. This is easy: a 2 MB process is automatically sent to the partition that fits it, and we need not worry about other spaces. But maintaining so many queues is an overhead — if processes come in many different sizes, the number of queues also becomes large. One queue per partition is not an optimal solution. Its one advantage: internal fragmentation does not arise, because each process lands in a partition matched to its size.
- A single queue. One queue is used by all processes — a 2 MB process or a 4 MB process, everything waits in the same queue, and the memory management unit takes the responsibility of finding the exact space for each process. This is the optimal solution on the queue side, but the system now has to search for the appropriate space every time.
The reference text draws the same contrast (Fig. 7.3): with one queue per partition each queue holds the processes destined for that partition, and processes are always assigned to minimize wasted memory; with a single queue, the smallest available partition that will hold the process is selected when it is time to load.
Comparison — queue organization:
| Option | Assignment | Overhead | Wasted space |
|---|---|---|---|
| One queue per partition | Process goes to its matching partition's queue | Many queues to maintain; grows with process-size variety | Minimal (process placed in a matching partition) |
| Single queue | MMU searches for the right space on each load | One queue, but a search on every placement | Possible unused partitions (e.g., a 16M partition idle while smaller processes wait) |
The professor's verdict: one queue per partition is not optimal (queue-count overhead); a single queue is optimal on the queue side but costs a search. In both cases a deeper limit remains.
In both cases, a deeper limit remains: the number of partitions specified at system time limits the number of active processes present in the system — active meaning currently running. If ten partitions were fixed at system generation time, no more than ten processes can ever be active, no matter how much memory is actually free or how small the processes are. That limit pushes us to the next technique, dynamic partitioning.
Exam note: expect the fixed-versus-dynamic comparison, internal fragmentation, and the degree of multiprogramming in questions on this module. The professor's key numbers to remember: the number of partitions fixed at system time limits the degree of multiprogramming and so the number of active processes.
Recap + bridge: fixed partitioning divides memory into static partitions at system time. A 4 MB process in an 8 MB partition wastes half (internal fragmentation); a process too big for every partition needs overlaying. Unequal partitions and one-queue-per-partition or a single queue ease the assignment, but the fixed partition count caps active processes. The natural next step — partitions created exactly as needed — is dynamic partitioning.
Real-world: IBM OS/360's MFT variant is the classic commercial deployment of fixed partitioning (multiprogramming with a fixed number of tasks). The lesson survives in modern systems wherever resources are pre-partitioned — for example, cloud virtual machines sized at creation time, where an instance smaller than its allocated size still pays for (and is bounded by) the whole allocation.
11.9 Dynamic Partitioning
11.9.1 The Basic Idea
Hook: Fixed partitioning is like booking hotel rooms of fixed sizes — a 14 MB guest in a 20 MB room wastes 6 MB, and the hotel cannot build a new wall mid-stay. Dynamic partitioning throws away the fixed walls: every guest gets a room carved exactly to their size.
Dynamic partitioning means the partitions are of variable sizes and lengths. The exact location of each partition can be found out, and the process is placed there. The memory is carved up exactly as needed, on demand. When a process arrives, the system measures the process and cuts a partition to fit — no internal fragmentation, because the allocation matches the process.
The reference text (Operating Systems: Internals and Design Principles, §7.2) describes the technique and its history: "With dynamic partitioning, the partitions are of variable length and number. When a process is brought into main memory, it is allocated exactly as much memory as it requires and no more." The important IBM system that used it was OS/MVT (multiprogramming with a variable number of tasks).
11.9.2 Worked Example: A 56 MB Memory
Worked example — the professor's board walkthrough. Walk through the example the professor built on the board. The system starts empty with 56 MB:
Process 1 arrives, size 20 MB, and occupies the first 20 MB of the 56 MB; 36 MB remains. Process 2 arrives:
Process 2 is 14 MB and occupies the next block; 22 MB remains. Process 3 arrives, 18 MB:
Process 3 takes 18 MB and only a 4 MB hole is left. Now process 4 arrives with 8 MB, and the leftover 4 MB is too small. The system has to remove one of the existing processes — say process 2 (14 MB) is not required as of now. Process 2 is swapped out to secondary storage, and its space is given to process 4:
Process 4 occupies 8 MB of process 2's old 14 MB, leaving 6 MB free there. Later, when process 1 is no longer required, it is removed — swapped to secondary storage — and process 2 is brought back, occupying 14 MB again.
By now the free space is scattered here and there. The total free space is:
but the 16 MB is not contiguous — it is split across several holes. Even if a 14 MB process arrives, the total is enough but the space is not one continuous block. That is the problem of dynamic partitioning: external fragmentation.
Sense-check: every arithmetic step above is simple subtraction of the process size from the remaining memory, and the final 6 + 6 + 4 = 16 MB free total matches the state on the board. The reference text runs the identical scenario in its Figure 7.4 — a 64 MB memory with an 8 MB operating system region, leaving exactly 56 MB of user memory — and reaches the same conclusion: the holes total 16 MB, and compaction would collect them into one 16 Mbyte block.
11.9.3 External Fragmentation versus Internal Fragmentation
External fragmentation: within the whole memory space, the remaining free spaces are scattered as small holes, so a request whose total size could fit cannot be satisfied because no single contiguous block is big enough. In the example above: 16 MB total free, but a 14 MB request still cannot be placed — the free space exists but is chopped into 6 + 6 + 4 MB pieces.
Internal fragmentation, by contrast, happens inside a single allocated space: after the process has occupied most of a partition, a small space like 1 MB or 2 MB is left out within the requested memory. Internal fragmentation is inside the allocated block; external fragmentation is between blocks, in the free space.
Comparison — the two fragmentations:
| Where the waste lives | Cause | Fix | |
|---|---|---|---|
| Internal fragmentation | Inside an allocated partition | Partition larger than the process (fixed partitioning) | Allocate exactly the process's size (dynamic partitioning) |
| External fragmentation | Between partitions, in the free space | Partitions of variable size removed and replaced, leaving scattered holes | Compaction — or paging |
The professor's one-line summary: internal fragmentation is inside the allocated block; external fragmentation is between blocks, in the free space. And notice the trade: dynamic partitioning eliminates the first only to create the second.
11.9.4 Compaction
To overcome external fragmentation we use compaction. Compaction shuffles the spaces to any one side: move the processes toward one side of memory and bring the free spaces together on the other side, so that a large hole is formed — large enough for the incoming process. The professor's picture: move this 6 MB down, move that one up, bring this down, like a shuffle. The reference text's description is the same: "the OS shifts the processes so they are contiguous and all of the free memory is together in one block", and in the example, compaction of the 6 + 6 + 4 MB holes produces one 16 MB block — sufficient for the 14 MB process that could not fit before.
Compaction is not an easy job. It is a complex, time-consuming process — time is wasted while the memory is being reorganized. Every moved process must have its relocation register (its base address) updated to its new position, and all that copying occupies the processor. The system also has to maintain two things: the spaces already allocated (the occupied partitions) and the free partitions, which we call holes. Because of the shuffling cost, dynamic partitioning is not a very best choice for memory management, and it is one reason the course moves on to paging later.
11.9.5 Maintaining the Hole List
Whenever a process needs memory, the system searches for a hole large enough. If the hole is large enough, one part of the hole is allocated to the arriving process and the rest of the hole is returned to the set of holes — the leftover keeps its status as free memory, ready for the next request. The set of holes — the free partitions — has to be maintained by the operating system. When a process terminates, its block of memory becomes free and is also returned to the free partitions. If a returned block sits next to an already-free partition, the two can be combined into one big hole for the next process. The reference text states this merging rule explicitly: "If the new hole is adjacent to other holes, these adjacent holes are merged to form one larger hole."
Recap + bridge: dynamic partitioning carves memory exactly per process — no internal fragmentation — but leaves scattered holes, producing external fragmentation (16 MB free but unusable in the example). Compaction shuffles processes to one side to re-collect the holes, at the price of costly copying; the OS maintains the hole list, splitting holes on allocation and merging neighbors on release. The next question is which hole the system should pick — the allocation schemes of the next section.
Real-world: dynamic partitioning with compaction was IBM OS/MVT's technique, used primarily in batch environments. The "shuffle" still exists in modern disguise: memory compacters and heap defragmenters in managed runtimes (Java's garbage-collecting compactors, for example) move live objects together to re-create large free regions — the same trade of copying cost against fragmentation that the professor described on the board.
11.10 Dynamic Storage Allocation Schemes: First Fit, Best Fit, Next Fit, Worst Fit
11.10.1 The Four Schemes
Hook: The hole list is full of candidate spots for a process. Which hole do you take? The answer is a placement policy — and the professor gives four classic ones, each with a different trade of speed against leftover size.
Purpose: dynamic storage allocation answers one question: given a list of free holes and a request of size n, which hole do we allocate? The choice shapes how quickly the memory fills with useless scraps (fragmentation), so the policy matters as much as the arithmetic.
The dynamic storage allocation can be done with one of four schemes:
- First fit. Scan the holes from the start; allocate whichever hole is the first one big enough. Remember that "hole" is another name for a free partition. Searching can stop as soon as a large-enough free hole is found — the reference text adds that the search can start at the beginning, or at the location where the previous search ended.
- Best fit. Search the entire list of holes; allocate the smallest hole that is big enough for the particular process. Unless the list is ordered by size, the whole list must be searched. This strategy produces the smallest leftover hole.
- Next fit. Start scanning from the location of the last allocation; allocate the next available block, moving around the memory from there. It avoids re-scanning the front of memory on every request, the way first fit does.
- Worst fit. Search the entire list; allocate the largest leftover hole. This strategy produces the largest leftover hole, which may be more useful than the small leftover from best fit.
We will see which one is better with an example.
11.10.2 Terminology: Holes Are Free Partitions
Q: These leftover spaces keep being called holes — what exactly is a hole?
A: A hole is just a free partition. The set of free partitions has to be maintained by the operating system, and in this context we call them holes.
The word "hole" is the professor's working vocabulary for the free list: a block of memory that is not allocated to any process and is large enough to receive one. The operating system maintains the set of holes — when a process terminates, its block returns to the set, and adjacent holes merge into one larger hole, as described in the dynamic partitioning section.
11.10.3 Worked Example: Requests of 40 MB, 20 MB, and 10 MB
Worked example — the four schemes against the same memory. Take a memory configuration at some point in time: the shaded (occupied) areas are already allocated, and the white areas are free. The free holes, in address order, are 20 MB, 60 MB, 40 MB, 16 MB, and 10 MB (the recording listed the sizes in a different order; the layout here reproduces every placement the professor made on the board under all four schemes). Three requests arrive: 40 MB, 20 MB, and 10 MB. The task is to give the starting block for each request under each scheme.
First fit — allocate the first hole that is big enough; each request scans from the start.
- 40 MB request: the 20 MB hole at the front is too small, and the 60 MB hole is the first one large enough. Allocate 40 MB from it; the remaining 20 MB stays free inside that block.
- 20 MB request: scanning again from the start, the 20 MB hole at the beginning is exactly enough — allocate it.
- 10 MB request: scanning from the start, the leftover 20 MB inside the old 60 MB block is the first hole big enough (the 16 MB and 10 MB holes sit later in address order). Allocate 10 MB; the remaining 10 MB stays free.
Best fit — search the entire list, take the smallest hole that is big enough.
- 40 MB request: the smallest hole that is big enough is the 40 MB hole itself, not the 60 MB one. Allocate it exactly.
- 20 MB request: the 20 MB hole at the front is exactly enough — allocate it.
- 10 MB request: search the whole list; the 10 MB hole is exactly enough — allocate it.
Next fit — start scanning from where the last placement happened. For this run, assume the most recently added block sits at the beginning of memory.
- 40 MB request: scanning from the beginning (the last placement), the 60 MB hole is the first big enough. Allocate 40 MB of it; the remaining 20 MB stays free there.
- 20 MB request: since the last placement was at the 60 MB block, the next scan starts right there, and the leftover 20 MB hole is available — it is occupied.
- 10 MB request: scanning continues from there, and as soon as the next hole large enough is found — the 40 MB hole — it is allocated, leaving 30 MB free in it.
Worst fit — search the entire list, take the largest hole.
- 40 MB request: the largest hole is the 60 MB one. Allocate 40 MB of it; the remaining 20 MB stays free.
- 20 MB request: searching the entire list, the largest hole big enough is the 40 MB one. Allocate 20 MB of it; the remaining 20 MB stays free.
- 10 MB request: the largest remaining hole is the leftover 20 MB from the 60 MB block. Half is allocated — 10 MB used, 10 MB free.
The comparison shows the differences between the schemes directly: first fit is fast but wastes space at the front of memory; best fit leaves the smallest leftovers but searches everything and fills up small holes quickly; next fit spreads allocations around the memory; worst fit keeps big holes available but leaves many medium pieces. Which is best depends on the workload — and that is exactly the kind of judgment the problems will test.
The professor paused during the best-fit trace to answer a student's doubt about the very first allocation:
Q: For best fit, will it consider the 60 MB hole or the 40 MB hole for this first 40 MB request?
A: It takes the 40 MB hole. Best fit always searches the entire list and picks the smallest hole that is big enough — here 40 MB fits exactly, so the 60 MB hole is left untouched for a larger process.
The doubt is understandable: the 60 MB hole is the one first fit would take, so it feels like the natural candidate. Best fit is a different rule — smallest hole that still fits — and its whole point is to save the larger holes for larger processes. The 40 MB hole disappears exactly, and the 60 MB hole survives for a future request that needs it.
Comparison — when to pick which:
| Scheme | Search cost | Leftover character | Practical verdict |
|---|---|---|---|
| First fit | Fast — stops at the first big enough hole | Small scraps accumulate at the front of memory | Simplest and usually the best and fastest (reference text) |
| Best fit | Slow — whole list, unless ordered by size | Smallest possible leftover; quickly litters memory with too-small holes | Despite the name, often the worst performer; compaction needed more often |
| Next fit | Moderate — resumes from the last placement | Breaks up the big block at the end of memory | Slightly worse than first fit; needs compaction more often |
| Worst fit | Slow — whole list | Largest leftover, keeps a big hole usable | Reference simulations rate it worse than first/best fit |
The professor's closing point: no scheme is universally best — the winner depends on the exact sequence of process sizes and swappings, which is why problems give you a fixed configuration and ask for each scheme's placements.
Pitfalls:
- Best fit is not "the biggest that fits" — it is the smallest hole that is big enough. Mixing this up reverses the whole trace.
- Next fit does not restart from the beginning. Its scan pointer moves on from the last placement; forgetting the pointer position breaks every subsequent placement.
- A hole that is "exactly enough" is still allocated — under best fit, a request of 20 MB takes the 20 MB hole, not the 40 MB one, even though both would fit.
- When a hole is larger than the request, the leftover returns to the free list — it is not lost; it becomes a smaller hole for later requests.
11.10.4 Homework Problem
For practice, the professor gave a homework problem: there are six partitions, given in a fixed order, and processes of given sizes to place in the same order, using first fit, best fit, and worst fit. Try to place each process in one of the blocks under each scheme, and discuss the results in the next session.
Exam note: the professor's homework mirrors the exam style: given a fixed list of partitions (or holes) and a fixed order of process requests, produce the placements under first fit, best fit, and worst fit — and expect the same for next fit. Always state which scheme you are applying and mark the leftover of each allocation; a single missed hole in the trace costs the placement.
Recap + bridge: four schemes allocate from the hole list: first fit (first big enough), best fit (smallest big enough), next fit (first big enough after the last placement), worst fit (largest hole). The same three requests of 40, 20, and 10 MB produced visibly different allocations under each scheme, and none is universally best. Next, the professor pulls back to the general view: what fragmentation is, and when compaction is even possible.
Real-world: every memory allocator in a real system is one of these policies in disguise. The C malloc library and operating-system allocators historically used first fit or best fit; Linux's slab and buddy allocators and Java's heap managers implement sized variants of these ideas. Understanding which leftover each policy leaves behind is exactly what allocation-policy engineers reason about when they tune a memory allocator for a specific workload.
11.11 Fragmentation in General and Compaction
11.11.1 What Fragmentation Is
Hook: You have 16 MB of memory free and still cannot run a 14 MB program. Fragmentation is the phenomenon that makes this possible — memory exists, but it is broken into pieces that are useless alone.
Fragmentation is the phenomenon in which the storage space is not used efficiently — we are not using the space properly. Because of fragmentation, the capacity of the system is reduced, and so is its performance. The professor then separated the two faces of the phenomenon:
- External fragmentation: the total memory space is enough to satisfy a request, but the space is not contiguous, so the request cannot be placed. The free memory exists, but only as scattered small holes — the 56 MB example of dynamic partitioning ended with 16 MB free and a 14 MB request still unplaceable.
- Internal fragmentation: the allocated memory is slightly larger than the requested memory; the difference in size is internal to the partition and is never used. The 4 MB process in the 8 MB fixed partition of section 11.8 wasted 4 MB this way.
The reference text quantifies how bad external fragmentation can get: statistical analysis of first fit shows that, given N allocated blocks, another 0.5N blocks are lost to fragmentation — meaning roughly one-third of memory may be unusable. This result is known as the 50-percent rule. So fragmentation is not a cosmetic problem; it can silently waste a large fraction of the machine's memory.
11.11.2 When Compaction Is Possible
To reduce external fragmentation, go for compaction: shuffle the contents, place all the allocated contents on one side and the free memory together on the other side. The simplest compaction algorithm is to move all processes toward one end of memory; all holes move in the other direction, producing one large hole of available memory.
But compaction is possible only if the relocation is dynamic — that is, if binding happens at execution time. If the binding is static — for example compile-time binding, where the code has absolute addresses — compaction is not possible, because moving the process would break its absolute addresses. Recall the three bindings from section 11.3: compile-time binding bakes absolute addresses into the binary, so shifting the process invalidates every reference; load-time binding is fixed at load and also cannot survive a move. Only execution-time binding, where the base/relocation register holds the current starting address, can track a moved process — after the move, the system simply loads the new base into the register and every address still resolves correctly.
Pitfall — the professor's exam flag: "compaction is possible only with dynamic relocation; static binding blocks it" is a direct question favourite. If a problem says the binding is compile-time, the answer is: compaction cannot be applied — the process has absolute addresses and cannot be moved.
The reference text confirms the same condition and adds the cost side: "If relocation is static and is done at assembly or load time, compaction cannot be done; compaction is possible only if relocation is dynamic and is done at execution time... This scheme can be expensive." When compaction is possible, its cost must be weighed: every moved byte is copied, every moved process's base register must be updated, and the processor is busy reorganizing memory instead of running processes — which is exactly why the course moves on to paging, where no such reorganization is ever needed.
This discussion of fragmentation leads directly into the extra topic of paging, covered in the next session.
Recap + bridge: fragmentation is inefficient use of storage — external when free space is non-contiguous (scattered holes), internal when the allocation is larger than the request (waste inside the partition). Compaction shuffles processes to one side to re-collect free memory, but it works only with dynamic (execution-time) relocation; static binding makes it impossible. Fragmentation's unacceptability is what pushes memory management into paging — the next session's topic.
Real-world: external fragmentation is the reason modern file systems and databases allocate space in fixed-size blocks rather than variable extents, and why virtual memory exists at all: paging lets every process's memory be non-contiguous, so free space never has to be contiguous to be useful. The 50-percent rule is also why allocators aggressively merge adjacent free regions (like the hole-merging rule of the previous section) before a compaction pass.
11.12 Assignment Workflow: The CPUOS Simulator
11.12.1 Assignment Logistics
The assignment is scheduled to start on 19 April, as per the handout. The professor plans to give a demo of the tool in the next session and will upload all references and the questions to the portal afterwards; the questions can be handed out only once the number of groups is known, so students were asked to confirm in their batch groups how many groups will do the assignment together and who will work alone.
Exam note / assignment note: the deliverable is a PDF of screenshots taken from the CPUOS simulator, showing every step of the assigned question. Watch the next session's demo — the professor said it will walk through the tool before the questions are released.
11.12.2 What the CPUOS Simulator Is
The assignment runs on a tool called the CPUOS simulator. It occupies only a small space on your system, so it can be downloaded easily. It is called CPUOS because you can visualize the working of the CPU and the working of the operating system in parallel, side by side: the CPU side shows the instructions being executed, and the OS side shows the processes, queues, and memory structures that the instructions wake up.
11.12.3 The Working Steps
Purpose: the simulator turns abstract scheduling and memory concepts into visible, inspectable states — you see the process move through the queue into the running state instead of merely reading about it.
Inputs & outputs: input is a small program (the assignment's source code, or one you write yourself, like the FCFS example below); output is a set of visual panels — utilization, process states, memory, resources, libraries, and a process list — that you capture as screenshots.
The workflow:
- Place and compile. The source code for the question is placed in the simulator and compiled. If the code is proper, the next step happens correctly.
- Load into memory. Loading it into memory is a button click. The load step places the compiled program, ready to run.
- Create processes. As an example, take FCFS scheduling: create four processes, and once they are created they are placed in the queue, which can be visualized with the simulator. With the help of the boards, you can create three or four different processes; all of them appear, and each one can be clicked and inspected.
- Observe the states. Once placed, a process sits in the ready queue. If it arrives late, it waits there; when running, the process is shown in the running state. The observations are the point of the assignment: seeing the arrival-delay effect — a process that arrives two or three seconds after the start — you can watch it wait and then move to the ready queue for execution.
- Choose the scheduling type. The simulator offers three: FCFS, Round Robin (for which you select the time slice), and Priority scheduling (for which you fix the priority). You can also set the lifetime of a process, how many number of ticks it runs, and a delay.
- Inspect the views. The views available in the simulator cover utilization, process states, memory, resources, and libraries, plus the process list. You can suspend the execution to see how the system looks and then continue it — so you can pause at the interesting moment and capture the screenshot.
Trace — the FCFS demo scenario. Create four processes in the simulator. All four appear on the board; place them so that one arrives with a delay of two to three seconds. Run under FCFS: the three early processes are created and sit in the ready queue; the delayed process is still arriving while they are dispatched. Watch the first process leave the ready queue and enter the running state, run for its lifetime (ticks), and then the next process take over. Suspend at the moment the delayed process joins the queue tail and capture the process-state and queue views — that screenshot is the deliverable for this question. For the FCFS question, the program itself is not given: you write your own small program, using the available codes as reference; the aim is only to show how FCFS works, with the burst time changed per process.
11.12.4 Beyond Scheduling: Synchronization, Deadlocks, and the Virtual Lab
The same simulator covers not only scheduling but also synchronization and deadlocks. The lab sheet was downloaded from the platform; a reference walkthrough is available (the professor opened the deadlock example, which shows the step-by-step process), and the same procedure is used for questions on threads, synchronization, or deadlocks — only the code changes. Whatever code the assignment question gives, you enter it, compile it, and load it.
Q: Can you access the virtual lab? Do we have the username and password?
A: Not yet — I have not tried it so far. But we did use this kind of simulator in the digital electronics and microprocessors course last semester, to study the instructions and registers, so we are familiar with the CPUOS-style tool.
The point of the exchange: access to the Platify virtual lab is still unconfirmed at the time of the lecture, but the tool family is already familiar from the microprocessors course — the simulator's look and workflow should not be a surprise to anyone who used the earlier one.
Real-world: tools like this simulator show what happens inside the CPU and OS when a program runs, which is exactly the kind of visualization used in real systems courses and in teaching operating systems in industry training — the same panels (process states, queues, utilization) that production monitoring dashboards show for real machines.
The assignment deliverable: you take screenshots of all the steps from the simulator and paste them into a PDF. For the FCFS question, the program itself is not given — you write your own small program, using the available codes as reference; the aim is only to show how FCFS works, with the burst time changed per process. For the critical-section-style questions, the code uses one variable G shared by two threads — one thread loops 5 times, the other 15 times — and the question asks whether there is a difference in the values of A and B and what the reason is, which you answer based on the concepts studied. If there is no symbol table requirement, it is not needed.
Recap: the assignment pipeline is compile → load → create processes → select the scheduling type → observe states and views → suspend, screenshot, and explain. FCFS is demonstrated with your own small program; synchronization questions run two threads on a shared variable G; every answer is documented with simulator screenshots pasted into a PDF.
11.13 Makeup Exam Walkthrough: Scheduling and Synchronization Review
The session ended with a discussion of the makeup exam paper — the paper the student had just written — which doubled as a review of scheduling and synchronization. The professor went question by question, and each question below is a review point plus a marking lesson.
11.13.1 The Scheduling Question (Seven Marks)
The scheduling problem asked for the average waiting time, turnaround time, and waiting time, computed for a set of processes. The professor's marking rule: if everything is correct, you get the marks; if even one thing is wrong, everything is wrong — all or nothing. So the presentation matters: show the time chart (Gantt chart) and put the results in a table. Some students ran the processes separately and never showed the time chart; those answers were not credited. Two or three others appeared to follow the identical procedure, process by process — writing the first two processes, then three, then four — and were marked accordingly.
Pitfall — the professor's all-or-nothing warning: for any scheduling question, draw the time chart and the table; a missing chart or a single wrong value can cost the whole seven marks. The all-or-nothing rule means one wrong waiting-time value invalidates the entire answer — check every number twice before handing in.
Exam note: expect to compute average waiting time, turnaround time, and waiting time for a set of processes. The required structure: a Gantt (time) chart showing the process sequence on the CPU, then a table of per-process values and the averages. Answers without the chart were not credited in the makeup paper.
11.13.2 The Three-Mark Difference Question
A three-mark question asked for a difference between two concepts. The marking: two marks for the difference itself and one mark for examples. You should be able to give at least minimum three points plus some examples — the examples earn the third mark.
Exam note: for difference questions, structure the answer as: at least three distinct points of difference (two marks) plus examples (one mark). Answers that only restate the definition without contrasting, or without examples, lose marks even if the difference is understood.
11.13.3 True or False with Justification
For the true-or-false questions, the rule is strict: writing just "true" or "false" earns nothing, and an improper justification also loses the marks. Only the first and the last statements were true — the first being that the layered approach is better, and the last concerning process states (that more than one process may be in the new state at the same time). The other statements were false, and the statements themselves made that clear. The professor went through them:
Q: "None of the process synchronization tools will cause deadlock" — is that true?
A: No, it is false. Every synchronization tool — semaphore, monitor, whatever it is — can cause deadlock. If some set of processes is there, one is holding a resource and another set of processes is using a resource while waiting for the one held by another process, that is a deadlock, and it can happen with any tool.
The misconception being corrected: "well-designed tools must be safe". The truth: the tools prevent races, not deadlocks. The reference text's semaphore example shows exactly this — two processes P0 and P1, each holding one semaphore and waiting for the other's, deadlock despite using semaphores correctly. Deadlock needs its four conditions to hold together (mutual exclusion, hold and wait, no preemption, circular wait); no synchronization tool removes them by itself.
The deadlock point is worth restating: one process holds a resource, another process (or set of processes) is using a resource and waiting for the resource held by the first — circular wait — and the system grinds to a halt. This is the classic deadlock situation from the synchronization module.
Q: Is FCFS a better choice for interactive processes, like gaming?
A: No. FCFS is not good for interactive processes. It always runs processes sequentially, and that takes a long time, which produces the camera effect — so it is always troublesome for time-sharing systems.
The "camera effect" is the professor's picture of the failure: under FCFS, a long process holds the CPU and the interactive processes behind it stall — like a camera shutter that stays closed while the queue waits, the display freezes. FCFS suits batch work, where each process runs to completion anyway; interactive systems need preemptive scheduling such as round robin.
Q: Do processor-specific queues increase the overall efficiency of the throughput?
A: No, that statement is false. As per queuing theory, if you have a single queue for multiple common resources, the waiting time decreases and the throughput increases — the overall efficiency goes up. With multiple processors and processor-specific queues, that gain does not happen.
The intuition behind the queuing-theory result: with a single shared queue, an idle processor can always take the next waiting job — no processor is ever idle while work waits in another queue. With separate per-processor queues, a job waiting in one queue cannot be served by an idle processor elsewhere, so the average waiting time grows and throughput drops.
11.13.4 Kernel Mode and User Mode
Q: The two modes — one is executed on behalf of the system and the other on behalf of the user — which are they?
A: The kernel mode is executed on behalf of the system, and the user mode is executed on behalf of the user. Even if you wrote only these two points about kernel and user mode, it is enough for the marks.
The two modes are the hardware privilege levels of the processor: kernel (system) mode can execute privileged instructions (like loading the base and limit registers from section 11.4) and access the operating system's memory; user mode runs application code and is blocked from both. The processor switches to kernel mode on system calls, interrupts, and traps — which is also how the base-and-limit protection is enforced.
11.13.5 CPU Utilization: The 23% Computation
The utilization problem asked for the percentage of time the CPU is busy. The accepted answer was 23 percent. The common mistake: everyone simply added all the numbers and divided by the total — but the denominator has to be taken per process.
Worked example — the per-process fractions. The professor's method: each process contributes its own numerator of 8 milliseconds, and the period is "8 milliseconds plus 18" for every process; the fraction for each process is 8 over that period, and the total percentage of time is found by adding all these fractions:
The intermediate arithmetic in the recording was garbled — the professor's cumulative sums ("8 plus 18, so 88, 108, that is 118") could not be transcribed exactly — but the method and the accepted result are unambiguous: compute a fraction per process (the process's own CPU time over its own period), sum the fractions, and multiply by 100. The per-process denominator is the tested skill; the specific period values on the exam paper are what produce 23 percent.
Sense-check: the answer stays a percentage between 0 and 100, and every process contributes its own fraction — so a process that uses little CPU adds a small fraction, and the total is the sum of the individual contributions.
Pitfall — the exam's own trap: "adding all the numbers and dividing once" is wrong because processes have different periods. Each process's fraction uses its own period in the denominator — the professor repeated this during the walkthrough because it was the mistake most students made.
Exam note: for utilization questions, apply the per-process fraction to each process and then sum; do not just add and divide once. Write the sum of fractions explicitly in the answer so the marking can see the per-process denominators.
11.13.6 The Robust Synchronization Tool (Five Marks)
A five-mark question asked to identify the robust (strongest) synchronization tool, take an example, and explain it. The marking: one mark for identifying the tool, some two marks for the explanation, and the rest for the usage with an example; without the usage or example, at most one or two marks. One student wrote mutex and explained the log/lock times, which earned partial credit.
The review answer: among all the tools, semaphore is the preferred one. The historical line of tools: first the lock (the mutex), then hardware-based synchronization support, then the semaphore, and then the monitors — monitors are programming-based, built on an abstract data structure. Even though the semaphore cannot avoid deadlocks either, it is the simple one and it is the best among them all.
Exam note: the five marks split as: one for naming the tool, two for the explanation, two for usage with an example. The preferred tool is the semaphore. Know the sequence lock (mutex) → hardware support → semaphore → monitor, and remember that even the semaphore cannot avoid deadlock — pairing the tool with a worked example (for example, two processes on a shared counter with wait/signal operations) earns the usage marks.
11.13.7 Process Creation and Termination (Four Marks)
The last question asked for the possible reasons for process creation and termination, worth four marks: two points plus explanation each (the professor's phrasing: "at least some two points, and then they should have explained").
Reasons for creation: the fork command, so that a child process is created; two processes that have to run concurrently; creating a duplicate of a process; or creating a new program and loading it. Reasons for termination: the process has exceeded its usage of resources; it is no longer required; or the parent exits, in which case the child also exits.
The reference text frames the same reasons: a process is created when a new batch job is submitted, when a user logs in interactively, when an OS process creates one to provide a service, or when an existing process spawns a child (in UNIX, via fork — the child is a duplicate of the parent; exec then loads a new program into the child). A process terminates when it finishes executing (normal exit), when it hits a fatal error, when it is killed by another process, or when its parent terminates.
Exam note: creation and termination answers are marked as "two points plus explanation" each — name the reason and explain it in one line; four marks total means two reasons for creation and two for termination, each with its explanation. Creation: fork → child; concurrent execution of two processes; duplicate of a process; create a new program and load it. Termination: exceeded resource usage; no longer required; parent exits → child exits.
Exam Guidance Summary
- Module weight: Memory management is a very important module. The problems connected with the techniques will be solved in the next session, after the techniques themselves.
- Scheduling questions: expect to compute average waiting time, turnaround time, and waiting time. Draw the time chart (Gantt chart) and present the results in a table — the marking is all-or-nothing: one wrong value can lose the entire seven marks. Students who ran the processes separately without showing the time chart were not credited.
- Difference questions (3 marks): give at least three points plus examples; two marks for the difference, one mark for the examples.
- True or false: always write the justification; "true"/"false" alone earns no marks. In the makeup paper only the first (layered approach is better) and the last (more than one process in the new state) were true; the statements about synchronization tools never causing deadlock, FCFS being good for interactive processes, and processor-specific queues increasing efficiency were all false.
- Utilization questions: the denominator must be taken per process — apply the per-process fraction (8 ms over the period) to every process and sum the fractions; the accepted answer was 23%. Simply adding everything and dividing once loses the marks.
- Synchronization tool questions (5 marks): the marks split as one for naming the tool, two for explanation, and two for usage with an example. The preferred tool is the semaphore; know the sequence lock (mutex) → hardware support → semaphore → monitor, and remember that even the semaphore cannot avoid deadlock.
- Process creation/termination (4 marks): two points plus explanation for each. Creation: fork command → child; concurrent execution of two processes; duplicate of a process; create a new program and load it. Termination: exceeded resource usage; no longer required; parent exits → child exits.
- Kernel vs user mode: kernel mode is executed on behalf of the system, user mode on behalf of the user.
- Homework: six partitions in a fixed order; place processes of given sizes using first fit, best fit, and worst fit; results are discussed next session.
- Assignment: starts 19 April per the handout; demo next session; questions depend on the number of groups; use the CPUOS simulator, take screenshots, paste them into a PDF; references will be uploaded on the portal and in the group.
Key Industry Applications
- IBM OS 360: the classic example of multiprogramming with a fixed number of tasks — fixed partitioning in a real commercial operating system (MFT; its variable-size relative MVT used dynamic partitioning).
- Base and limit registers / MMU: the hardware mechanism for relocation and protection is present in real CPUs; every modern system translates logical to physical addresses with a memory management unit — the same addition of a relocation register happens on every memory reference, now generalized far beyond one register.
- Shared memory: threads sharing global variables and memory-mapped files between processes work exactly as described — the shared portion must be resident in main memory and the process carries only references.
- Segmentation: large enterprise programs written as modules, compiled separately, with read-only and execute-only protections, map directly onto segmented memory models.
- CPUOS simulator: the assignment tool that visualizes CPU and operating system working in parallel — scheduling (FCFS, Round Robin with time slice, Priority), synchronization, and deadlock, with views for utilization, process states, memory, resources, libraries, and process list.
- Platify virtual lab: the online lab platform used alongside the simulator, which students had already used in the microprocessors course.
- Synchronization tools: Peterson solution, locks, semaphores, and monitors as the standard toolset used to manage shared memory access in real concurrent programs — including the warning that no tool, not even the semaphore, prevents deadlock by itself.
OS Lecture 11 notes · Memory Management
Sections Breakdown
The three levels of memory (main, secondary, tertiary), why the OS places and swaps processes, and the five requirements of good memory management.
Relocation, protection, sharing, logical organization, and physical organization, and how they interact.
Relocation as loading a process at different locations; address binding at compile time, load time, and execution time.
The base register, the limit register, the legal address range, the hardware checking flow, and privileged instructions.
How several processes access the same portion of memory, with the shared portion resident and references carried by programs.
Programs as separately compiled modules, protection modes (read only, execute only), and the path toward segmentation.
Main memory versus secondary storage, logical/virtual versus physical addresses, the relocation register, and dynamic relocation.
Static partitions set at system time, internal fragmentation, the 8 MB worked example, and queue organizations.
Variable-size partitions, the 56 MB worked example, external fragmentation, compaction, and hole management.
The four placement policies traced against 40 MB, 20 MB, and 10 MB requests.
External versus internal fragmentation, the 50-percent rule, and when compaction is possible.
The assignment workflow: compile, load, create processes, choose a scheduling type, and capture screenshots into a PDF.
Exam lessons: Gantt charts, difference questions, true/false justifications, utilization fractions, semaphores, and process creation and termination.
Consolidated exam strategy for the memory management module and the makeup paper.
Where the lecture's ideas live in real systems: IBM OS/360, memory management units, shared memory, and synchronization tools.
Exam Revision Notes
Below is the distilled, exam-ready core. Every entry comes from the full explanation above. Use this section for rapid review; return to the main notes when a point needs more context.
Memory Management: Module Overview
Must-know: Memory management is a very important module; the OS handles placement, swapping out, and bringing back of processes across main memory, secondary storage, and tertiary storage, guided by five requirements: relocation, protection, sharing, logical organization, physical organization.
⚠️ Top pitfall: Assuming the programmer decides where a process sits in memory; in fact the operating system alone manages placement and swapping.
Self-check: What are the three levels of memory and the five requirements of memory management?
The Five Requirements of Memory Management
Must-know: List the five requirements: relocation (place/run a process at different locations at different times), protection (processes safe from each other), sharing (several processes access the same portion of memory), logical organization (program modules arranged in memory), physical organization (placement onto physical hardware).
⚠️ Top pitfall: Treating the five requirements as isolated memorization items; they interact (relocation + protection = base/limit registers; sharing links to synchronization).
Self-check: Which two requirements combine to give the base and limit register mechanism?
Relocation and Address Binding
Must-know: Relocation = loading a process at different locations at different times. Address binding = mapping one address space to another, at three stages: compile time (absolute code; recompile on move), load time (relocatable code; loader fixes up), execution time (delayed until run; needs base/limit hardware).
⚠️ Top pitfall: Thinking relocation means the process must be recompiled; only compile-time binding does, execution-time binding handles moves for free.
Self-check: Which binding stage allows a process to be moved in memory while it is running?
Protection with Base and Limit Registers
Must-know: Base register = starting/smallest legal physical address; limit register = size of the range; size of the process range = base + limit. Check flow: base <= logical address <= base + limit, else trap; physical address = base + logical. Only the OS (privileged instruction, kernel mode) can load the registers.
⚠️ Top pitfall: Forgetting the limit side of the fence: an address above base + limit is as illegal as one below base; both trap to the OS.
Self-check: With base = 300040 and limit = 120900, which addresses are legal for the process?
Sharing Memory Between Processes
Must-know: Sharing = several processes access the same portion of memory. No cross-memory accessibility is given to processes by default; when sharing is wanted, the shared portion must be resident in main memory and the process carries only references, resolved by the MMU.
⚠️ Top pitfall: Assuming shared data in secondary storage can be accessed directly; it must first be brought into main memory for the process to execute.
Self-check: What must be true of the shared portion of memory when two processes share it?
Logical Organization of Memory
Must-know: Logical organization = programs as separately compiled modules; protection modes (read only, execute only); modules can be shared; program divided into segments, each checked against its limit — segmentation, covered later.
⚠️ Top pitfall: Assuming all modules are equally accessible; protection modes (read only / execute only) control what may be done with each module.
Self-check: What protection modes can modules have, and what is the name of the technique that divides a program into checked segments?
Physical Organization and Address Spaces
Must-know: Logical (virtual) address: CPU-generated, range 0..max. Physical address: seen by the memory unit, range R+0..R+max. Physical = logical + R, where R is the relocation register; the MMU performs the addition on every reference (e.g., 346 + 14000 = 14346).
⚠️ Top pitfall: Thinking the user program sees physical addresses; the user sees only logical addresses and the MMU performs the mapping.
Self-check: If the relocation register holds 14000, what physical address does logical address 346 map to?
Fixed Partitioning
Must-know: Fixed partitioning: static partitions set at system time; degree of multiprogramming limited by partition count; 8 MB partition with a 4 MB process wastes half (internal fragmentation); a 5 MB process cannot fit the leftover; overlaying when nothing fits.
⚠️ Top pitfall: Thinking leftover space inside an allocated partition is reusable; internal fragmentation is dead space until the process leaves.
Self-check: In a system with ten fixed partitions, how many processes can be active at the same time?
Dynamic Partitioning
Must-know: Dynamic partitioning: partitions of variable size, allocated exactly as needed; trace: 56-20=36, 36-14=22, 22-18=4 (hole); swap 2 out, place 4 (8 MB): 14-8=6; free totals 6+6+4=16 MB but not contiguous (external fragmentation). Compaction shuffles processes to one side; hole list maintained with splitting and merging.
⚠️ Top pitfall: Assuming total free space can satisfy a request; external fragmentation means only a single contiguous block big enough counts.
Self-check: After the 56 MB walkthrough, why can a 14 MB process not be placed even though 16 MB is free?
Dynamic Storage Allocation Schemes: First Fit, Best Fit, Next Fit, Worst Fit
Must-know: First fit: first hole big enough from the start. Best fit: smallest hole big enough (search whole list) — e.g., 40 MB request takes the 40 MB hole, not the 60 MB one. Next fit: continue from the last placement. Worst fit: largest hole. A hole is a free partition.
⚠️ Top pitfall: Best fit picks the smallest hole that is big enough, not the biggest; next fit does not restart from the beginning.
Self-check: For a 40 MB request with holes 20, 60, 40, 16, 10 MB, which hole does best fit take and why?
Fragmentation in General and Compaction
Must-know: External fragmentation: total space enough but not contiguous. Internal fragmentation: allocation larger than request, waste inside the partition. Compaction requires dynamic (execution-time) relocation; with static/compile-time binding, compaction is impossible because absolute addresses would break.
⚠️ Top pitfall: Claiming compaction is possible with compile-time binding; static binding means absolute addresses that break when the process moves.
Self-check: Why is compaction impossible when binding is compile-time?
Assignment Workflow: The CPUOS Simulator
Must-know: CPUOS simulator workflow: place source code, compile, load (button click), create processes (e.g., four under FCFS), select scheduling type (FCFS / Round Robin with time slice / Priority), set lifetime, ticks, delay; views: utilization, process states, memory, resources, libraries, process list; suspend and continue; screenshots into a PDF.
⚠️ Top pitfall: Running processes separately without showing the queue/state views; the deliverable is screenshots of each step, not just results.
Self-check: What three scheduling types does the CPUOS simulator offer?
Makeup Exam Walkthrough: Scheduling and Synchronization Review
Must-know: Scheduling (7 marks): Gantt chart + table; all-or-nothing. Difference (3): three points + examples (2+1). True/false: justification mandatory; every sync tool (semaphore, monitor) can deadlock; FCFS bad for interactive (camera effect); single queue beats per-processor queues. Utilization: per-process denominator, sum fractions = 23%. Robust tool (5): semaphore; 1 name + 2 explanation + 2 usage. Creation/termination (4): two points + explanation each.
⚠️ Top pitfall: Adding all the numbers and dividing once for utilization; the denominator must be taken per process.
Self-check: Why can every synchronization tool cause deadlock, including semaphores and monitors?
Exam Guidance Summary
Must-know: Module weight: very important; problems solved next session. Scheduling (7 marks): Gantt chart + table, all-or-nothing. Difference (3 marks): three points + examples. True/false: justification mandatory. Utilization: per-process denominator, sum fractions, 23%. Sync tool (5 marks): semaphore, 1+2+2. Creation/termination (4 marks): two points + explanation each. Homework: six partitions with first/best/worst fit. Assignment: 19 April, CPUOS simulator, screenshots into PDF.
⚠️ Top pitfall: Answering true/false without justification or computing utilization with a single global denominator; both lose all marks.
Self-check: How are the five marks split for the robust synchronization tool question?
Key Industry Applications
Must-know: IBM OS/360 = fixed partitioning (MFT) and dynamic partitioning (MVT); MMU translates logical to physical addresses in every modern system; memory-mapped files and shared libraries are real sharing; segmentation maps onto modular enterprise programs; CPUOS simulator visualizes CPU + OS; semaphores/monitors are the standard concurrency toolset but none prevents deadlock by itself.
⚠️ Top pitfall: Assuming synchronization tools prevent deadlock by design; every tool, including semaphore and monitor, can deadlock.
Self-check: Which IBM OS/360 variant used fixed partitioning, and which used dynamic partitioning?
Was this lecture useful?
BitsNotes AI Assistant
Subject Notes AssistantConfigure AI Chat
Choose how to access the chatbotSigned in as
Powered by BitsNotes — 20 messages per day. No API key needed. Want unlimited access? Use "Bring Your Own Key" mode.
Sign in to use AI Chat
Get 20 free AI messages per day to ask questions about your lecture notes. Sign in with Google or GitHub — it takes 5 seconds.
Sign In to BitsNotesSwitch to "Bring Your Own Key" tab above for unlimited access with any OpenAI-compatible provider.