Overview

Relevant source files

The memory_set crate provides building blocks for memory mapping management in Rust, offering data structures and operations similar to Unix system calls like mmap, munmap, and mprotect. This document covers the core architecture, components, and design patterns of the memory management system.

Note: This repository has been archived and the code has been moved to the axmm_crates repository as indicated in the README.

For detailed implementation specifics of individual components, see Implementation Details. For practical usage examples and patterns, see Usage and Examples.

Core Components and Structure

The memory_set crate is built around three primary components that work together to provide flexible memory mapping management:

Core Components Overview

flowchart TD
subgraph Storage["Storage"]
    BT["BTreeMap<VirtAddr, MemoryArea>"]
end
subgraph subGraph1["Supporting Types"]
    MR["MappingResult<T>"]
    ME["MappingError"]
    VA["VirtAddr"]
    VAR["VirtAddrRange"]
end
subgraph subGraph0["Primary Types"]
    MS["MemorySet<F,PT,B>"]
    MA["MemoryArea<F,B>"]
    MB["MappingBackend<F,PT> trait"]
end

MA --> MB
MA --> VAR
MR --> ME
MS --> BT
MS --> MA
MS --> MR
VAR --> VA

Sources: src/lib.rs(L12 - L13)  src/lib.rs(L15 - L27)  README.md(L18 - L41) 

The system uses a generic type parameter approach where:

  • F represents memory flags (must implement Copy)
  • PT represents the page table type
  • B represents the mapping backend implementation

System Architecture and Data Flow

The memory management system follows a layered architecture where high-level operations are decomposed into area management and low-level page table manipulation:

Memory Management Operation Flow

sequenceDiagram
    participant Client as Client
    participant MemorySet as MemorySet
    participant BTreeMap as BTreeMap
    participant MemoryArea as MemoryArea
    participant MappingBackend as MappingBackend

    Note over Client,MappingBackend: map() operation
    Client ->> MemorySet: "map(area, page_table, unmap_overlap)"
    MemorySet ->> BTreeMap: "Check for overlaps"
    BTreeMap -->> MemorySet: "Overlapping areas found"
    alt unmap_overlap = true
        MemorySet ->> MemorySet: "Split/remove overlapping areas"
        MemorySet ->> MappingBackend: "unmap existing regions"
    else unmap_overlap = false
        MemorySet -->> Client: "MappingError::AlreadyExists"
    end
    MemorySet ->> MemoryArea: "Get backend reference"
    MemoryArea ->> MappingBackend: "map(start, size, flags, page_table)"
    MappingBackend -->> MemorySet: "Success/failure"
    MemorySet ->> BTreeMap: "Insert new area"
    MemorySet -->> Client: "MappingResult"
    Note over Client,MappingBackend: unmap() operation
    Client ->> MemorySet: "unmap(start, size, page_table)"
    MemorySet ->> BTreeMap: "Find affected areas"
    loop For each affected area
    alt Fully contained
        MemorySet ->> BTreeMap: "Remove area"
    else Partially overlapping
        MemorySet ->> MemoryArea: "split(boundary_addr)"
        MemoryArea -->> MemorySet: "New area created"
        MemorySet ->> BTreeMap: "Update area collection"
    end
    MemorySet ->> MappingBackend: "unmap(start, size, page_table)"
    end
    MemorySet -->> Client: "MappingResult"

Sources: README.md(L36 - L48)  src/lib.rs(L15 - L27) 

Generic Type System Design

The crate achieves flexibility through careful use of Rust generics, allowing different implementations for flags, page tables, and backends while maintaining type safety:

Generic Type Relationships

flowchart TD
subgraph subGraph2["Mock Implementation Example"]
    MF["MockFlags = u8"]
    MPT["MockPageTable = [u8; MAX_ADDR]"]
    MOCK["MockBackend"]
    MS_CONCRETE["MemorySet<MockFlags, MockPageTable, MockBackend>"]
end
subgraph subGraph1["Core Generic Types"]
    MS["MemorySet<F,PT,B>"]
    MA["MemoryArea<F,B>"]
    MBT["MappingBackend<F,PT>"]
end
subgraph subGraph0["Generic Parameters"]
    F["F: Copy"]
    PT["PT"]
    B["B: MappingBackend<F,PT>"]
end

B --> MA
B --> MBT
B --> MS
F --> MA
F --> MBT
F --> MS
MF --> MS_CONCRETE
MOCK --> MBT
MOCK --> MS_CONCRETE
MPT --> MS_CONCRETE
PT --> MBT
PT --> MS

Sources: README.md(L24 - L34)  README.md(L51 - L87)  src/lib.rs(L12 - L13) 

Error Handling Strategy

The crate uses a dedicated error type system to handle various failure scenarios in memory operations:

Error TypeDescriptionUsage Context
MappingError::InvalidParamInvalid parameters likeaddr,size,flagsInput validation
MappingError::AlreadyExistsRange overlaps with existing mappingOverlap detection
MappingError::BadStateBackend page table in bad stateBackend operation failures

The MappingResult<T> type alias provides a convenient Result type for all memory operations, defaulting to MappingResult<()> for operations that return no meaningful data on success.

Sources: src/lib.rs(L15 - L27) 

Key Design Principles

  1. Generic Flexibility: The system uses three generic type parameters (F, PT, B) to allow customization of flags, page tables, and backend implementations
  2. Area-Based Management: Memory is managed in discrete areas that can be split, merged, and manipulated independently
  3. Backend Abstraction: The MappingBackend trait abstracts actual page table manipulation, enabling different implementation strategies
  4. Overlap Handling: Sophisticated overlap detection and resolution with options for automatic unmapping of conflicting regions
  5. Type Safety: Rust's type system ensures memory safety and prevents common memory management errors

This overview establishes the foundation for understanding the detailed implementation covered in Implementation Details and the practical usage patterns demonstrated in Usage and Examples.

Sources: README.md(L9 - L14)  src/lib.rs(L1 - L13)