Memory Management

15 Jul 2019

Memory Management

In the figure above, we want the newly active process P1 to execute in its own logical address space randing from 0 to max. It shouldn’t have to know exactly where in physical memory its code and data are located. This decouples the compiler from run-time execution. In addition, there needs to be a mapping from logical addresses to physical addresses at run time. This is taken care of by the Memory Management Unit (MMU).

The MMU must do the following:

  1. Address translation: translate logical addresses into physical addresses, i.e. map the logical address space into a physical address space.
  2. Bounds checking: check if the requested memory address is within the upper and lower limits of the address space. One approach is:
    • Base register in hardware keeps track of lower limit of the physical address space.
    • Limit register keeps track of size of logical space.
    • Upper limit of physical address space = base register + limit register.

Base and limit registers provide hardware support for a simple MMU.

  • Memory access should not go out of bounds.
  • If out of bounds, then this is a segmentation fault so trap to the OS.
  • MMU will detect out-of-bounds memory access and notify OS by throwing an exception. Only the OS can load the base and limit registers while in kernel/supervisor mode - these registers would be loaded as part of a context switch.

Loading Tasks into Memory

  • Contiguous memory is used to hold a task.
  • The task is stored as code and data on disk.
  • The task contains code, data, stack, and heap in memory.
  • Multiple tasks can be loaded in memory at the same time.
  • The kernel is responsible for protecting task memory from other tasks.
    • The MMU is used to validate all addresses.
    • Each task needs a base and limit register.
    • Context switch must save/restore these address registers.

Address Binding

  • Address binding at Compile Time
    • If you know in advance where in physical memory a process will be placed, then compile your code with absolute physical addresses.
    • Ex:
        LOAD MEM_ADDR_X, reg1
        STORE MEM_ADDR_Y, reg2
    • MEM_ADDR_X and MEM_ADDR_Y are hardwired by the compiler as absolute physical addresses.
  • Address Binding at Load Time
    • Code is first compiled in relocatable format.
    • Replace logical addresses in code with physical addresses during loading.
    • At load time, the loader replaces all occurrences in the code of MEM_ADDR_X and MEM_ADDR_Y with (base+MEM_ADDR_X) and (base+MEM_ADDR_Y).
    • Once the binary has been thus changed, it is not really portable to any other area of memory, hence load time bound processes are not suitable for swapping.
  • Address Binding at Run Time (done by most modern OS)
    • Code is first compiled in relocatable formate as if executing in its own logical/virtual address space.
    • As each instruction is executed, i.e. at run time, the MMU relocates the logical address to a physical address using hardware support such as base/relocation registers.
    • `MEM_ADDR_X is compiled as a logical address, and implicitly the hardware MMU will translate it to base+MEM_ADDR_X when the instruction executes.

The MMU needs to perform run-time mapping of logical/virtual addresses to physical addresses. * For run-time address binding, each logical address is relocated or translated by MMU to a physical address that is used to access main memory/RAM. Thus, the application program never sees the actual physical memory, it just presents a logical address to the MMU.

Let’s combine the MMU’s two tasks (bounds checking and memory mapping) into a single figure. * Since logical addresses can’t be negative, then a lower bound check is unnecessary; just check the upper bound by comparing it to the limit register. Also, by checking the limit first, there is no need to do relocation if out of bounds.

Run Time Binding

Static Linking

By using run time binding with static linking, applications have access to the same library code even if it has changed recently. This can move to machines without the library and involves self-contained processes.

Statically linked executable: * Logical addresses are translated instruction by instruction into physical addresses at run time and the entire executable has all the code it needs at compile time through static linking. * ONce a function is statically linked, it is embedded in the code and can’t be changed except through recompilation. The code may contain outdated functions that don’t have the latest bug fixes, performance optimizations, and/or feature enhancements.

Dynamic Linking

By using run time binding with dynamic linking, applications have access to the latest code at run-time, e.g. the most recent patched dlls. Other advantages are smaller size (stubs stay stubs unless activated) and that we can have just one copy of the code that is shared among all applications.