Memory Management

Memory Management

Address Space

Solving protection and relocation problems When a process runs, the starting physical address of the program is loaded into the base register, and the length is loaded into the limit register Dynamic relocation: Memory access instructions are reinterpreted by adding the value of the base register, checking if the address exceeds the limit, which will generate an error and terminate access Disadvantage: Requires addition and comparison operations, which can be slow without special circuits

Memory Overload

Swapping technique: Idle processes are stored on disk and do not occupy memory when not running Virtual memory: Running with only part of the process loaded into memory

Free Memory Management

By maintaining a linked list that records allocated memory segments and free memory segments, nodes in the linked list either contain a process or a free area between two processes

First fit: Scan through the linked list, split the free area into two halves to allocate unless sizes match exactly Next fit: Record the position of scanned free areas Best fit: Scan from beginning to end, find the smallest free area that can accommodate the process

Virtual Memory

Dividing the process address space into multiple pages, each having a continuous address range When the program waits for part of it to be read into memory, the CPU can be given to other processes to use

Virtual address: Virtual page number (high bits, used as page table index) + offset (low bits) Virtual page number -> Page table entry in page table -> Page frame number -> Replace virtual page number == Real physical address In using virtual addresses, when a process uses instructions to read memory, the virtual address is first sent to the MMU (Memory Management Unit that maintains the page table) to be mapped to a physical address. If not found (flag bit in page table entry is 0), a page fault interrupt occurs; if found, then send the physical address to the memory bus

Physical memory is divided into page frames, virtual address space is divided into pages, page frames and pages are usually the same size, and swapping with disk is done in whole page units

The page table for virtual addresses becomes larger and larger, easily causing performance problems, so TLB is introduced as a local cache for the page table. Modern operating systems can load TLB cache, and when the cache can hold enough entries, it is sufficient

Soft miss: In memory but not in TLB, just update TLB, no need to access disk Hard miss: Not in memory and not in TLB, read page from disk to memory 32-bit address space operating systems use multi-level page tables, 64-bit operating systems can design TLB as a hash table, virtual page tables with the same hash value will be in one bucket, with values as page frame numbers

Page Replacement Algorithms

LRU When page fault occurs, replace the page that has not been used for the longest time C++ implementation

class LRUCache 
{ 
    // store keys of cache 
    list<int> dq; 
  
    // store references of key in cache 
    unordered_map<int, list<int>::iterator> ma; 
    int csize; //maximum capacity of cache 
  
public: 
    LRUCache(int); 
    void refer(int); 
    void display(); 
};

LRUCache::LRUCache(int n) 
{ 
    csize = n; 
}

void LRUCache::refer(int x) 
{ 
    // not in cache
    if (ma.find(x) == ma.end()) 
    { 
        // full, delete tail element 
        if (dq.size() == csize) 
        { 
            //delete tail (longest unused) 
            int last = dq.back(); 
            dq.pop_back(); 
            ma.erase(last); 
        } 
    } 
  
    // also delete if in cache
    else
        dq.erase(ma[x]); 
  
    // insert at head and update reference 
    dq.push_front(x); 
    ma[x] = dq.begin(); 
}

Separating Data Space and Instruction Space

Paging data space and instruction space separately, using linker to determine when to use which space, can double the available address space Shared pages: Separated address spaces can better allow multiple processes to share read-only program pages Avoid releasing shared page tables: Let processes have their own page tables, but point to the same set of page tables If writing to read-only parts, the operating system’s copy-on-write mechanism will be triggered to create a copy

Dynamic Linking

Linking: Scanning .a files, searching for external functions undefined in the program, loading them to binary file when found Static linking wastes a lot of memory space because the system doesn’t know it can share these libraries Dynamic linking compilation process loads stubs that can dynamically bind called functions at runtime. If other processes have loaded this library when running, the library can be shared, avoiding duplicate loading of static linking Also, redistributing DLLs doesn’t require clients to recompile programs Multiple processes sharing the same library can be solved by generating relative address instructions during compilation, or using mmap to map files to part of their virtual address space, allowing inter-process communication through such shared memory

Segmentation of Virtual Address Space

Each segment constitutes an independent address space, requiring programs to provide segment number and address within segment, allowing stack segments to stretch freely, improving space utilization, and helping with protection and sharing

Combining Segmentation and Paging

In x86, CS register stores code segment selector, DS stores data segment selector. Segments are further divided into local segments (program segments) and global segments (system segments including the operating system itself), paging can be enabled or disabled, linear address composition == directory, page, offset

  • Text Segment: Memory mapping of executable file code
  • Data Segment: Memory mapping of initialized global variables of executable file
  • BSS Segment: Uninitialized global variables or static variables (initialized with zero page)
  • Heap: Store dynamic memory allocation, anonymous memory mapping
  • Stack: Process user space stack, automatically allocated and released by compiler, storing function parameter values, local variable values, etc.
  • Memory Mapping Segment: Any memory-mapped file

Differences Between Stack and Heap

Stack: Automatically allocated and released by compiler, storing function parameter values, local variable values, etc. Its operation method is similar to the stack in data structures Heap: Generally allocated and released by programmers, if programmers don’t release it, it may be reclaimed by OS when program ends

The Nature of Functions

The value of a function pointer is the address of the first instruction in the machine code representation of the function A function call requires: passing control (function pointer), passing data (passing 6 parameters through registers, exceeding ones placed on stack frame), recording the address of the next instruction after function returns, allocating space (stack pointer moves to lower address)