The Memory Manager

- memory manager's main tasks:

	1. allocate primary memory to processes
	2. map the process address space to physical memory locations
	3. move (copy) data between two consecutive levels of hierarchy 
	   as needed for most efficient use of the hierarchy

Program translation phases

how does source code get turned into an executing program? COMPILER LINKER LOADER source ----------> relocatable -----------> absolute ----------> executable code object module program program Compiler: - produces machine instructions with many addresses unknown - static data (static variable) and locally defined procedure entry addresses kept in symbol table Linker: - combines modules into a single text segment, single data segment - uses symbol table from each module to fill in the holes - assumes entire absolute program begins at address 0 Loader: - obtains portion of physical memory for program from the memory manager - translates (binds) absolute addresses of program to executable addresses

How is memory granted to each process?

- fixed partition strategies: - memory is carved up statically into a number of partitions (usually of varying sizes) - partition of adequate size is found for process if one exists (usually go for best fit) - a queue of processes may be assigned that memory area - each process waits to reach head of queue before being granted mem - leftover (unused) space is wasted: "internal fragmentation" - fixed partitions usually inadequate for interactive systems because memory needs of process vary over time - variable-partition strategies - start with memory treated as one big partition - allocate memory as needed (if available) - after memory is allocated in this way, some residual unallocated area may be left that is too small for any process: "external frag" - must keep track of free space (use linked list or other data struct) - when a process releases its memory, leaves a hole - when a process releases its memory Mi, that space can be reallocated to another process that needs Mj <= Mi - unused portion of partition (Mi-Mj): "internal frag" - if a process asks for more memory, have to find bigger partition - process then gets moved to this new space - memory manager keeps track of holes so that it can merge adjacent - eventually, too much fragmentation: need to compact memory - this requires moving all the processes to different address space ( often via secondary storage ) - what about the loader-bound physical addresses? - do we have to reload program?! strategies include: - best fit: find minimal sized partition >= needed size - worst fit: find largest block (good chance another proc can use left over space) - first fit: don't waste time searching - next fit: avoids over-fragmentation near beginning of list; use circular list of free blocks and keep track of last position

Swapping

- memory is a resource, just like CPU, I/O devices, etc. - processes compete for memory - what if there isn't enough to go around? - swapping: when a process is blocked (e.g. on an I/O request), process manager may elect to suspend it - at this point, memory manager can SWAP process out of primary memory, providing space of other ready processes to run - can also exploit to "swap out" ready processes that are idle (e.g. login session)

The Memory Hierarchy

- principle of locality: - sequential instructions mean that next memory reference is likely to be very close (spatial locality) - instruction loops tend to be fairly small, so repeated references to same memory location are likely to be close in time (temporal locality) - 90/10 rule "90% of program's time spent executing 10% of instructions" - in response to growing memory needs: concept of memory hierarchy - many possible levels: CPU registers, L1 cache, L2 cache, primary mem, disk, tape... - high levels are very fast, orders of magnitude more than those below