Page Iteration
Relevant source files
This document covers the page iteration functionality provided by the memory_addr
crate, specifically the PageIter
struct and its associated methods. Page iteration allows traversing memory addresses in fixed-size page increments, which is essential for memory management operations like mapping, unmapping, and allocating memory in page-aligned chunks.
For information about address types and basic operations, see Address Types and Operations. For address range operations, see Address Ranges.
Overview
The PageIter
struct provides a safe, type-safe iterator for traversing memory addresses in page-sized steps. It enforces alignment requirements and validates page sizes at construction time, ensuring that iteration only occurs over properly aligned memory regions.
PageIter Structure Design
Sources: memory_addr/src/iter.rs(L22 - L28) memory_addr/src/iter.rs(L50 - L65)
PageIter Structure and Parameters
The PageIter
struct is defined with two generic parameters that control its behavior:
Parameter | Type | Purpose |
---|---|---|
PAGE_SIZE | const usize | Compile-time constant specifying page size in bytes |
A | Type bound byMemoryAddr | Address type (e.g.,PhysAddr,VirtAddr,usize) |
The struct contains two fields:
start
: Current position in the iterationend
: End boundary (exclusive) for the iteration
The PAGE_SIZE
parameter must be a power of 2, and both start
and end
addresses must be aligned to PAGE_SIZE
boundaries.
Sources: memory_addr/src/iter.rs(L22 - L28)
Creating PageIter Instances
PageIter Construction Flow
flowchart TD Start["PageIter::new(start, end)"] CheckPowerOf2["PAGE_SIZE.is_power_of_two()"] ReturnNone["Return None"] CheckStartAlign["start.is_aligned(PAGE_SIZE)"] CheckEndAlign["end.is_aligned(PAGE_SIZE)"] CreateIter["Create PageIter instance"] ReturnSome["Return Some(PageIter)"] CheckEndAlign --> CreateIter CheckEndAlign --> ReturnNone CheckPowerOf2 --> CheckStartAlign CheckPowerOf2 --> ReturnNone CheckStartAlign --> CheckEndAlign CheckStartAlign --> ReturnNone CreateIter --> ReturnSome Start --> CheckPowerOf2
Sources: memory_addr/src/iter.rs(L34 - L47)
The new
method performs several validation checks:
- Page Size Validation: Ensures
PAGE_SIZE
is a power of 2 - Start Address Alignment: Verifies
start
is aligned toPAGE_SIZE
- End Address Alignment: Verifies
end
is aligned toPAGE_SIZE
If any validation fails, the method returns None
. Otherwise, it returns Some(PageIter)
with the validated parameters.
Iterator Implementation
The PageIter
implements the Iterator
trait, yielding addresses of type A
on each iteration:
Iterator Mechanics
sequenceDiagram participant Client as Client participant PageIterinstance as "PageIter instance" participant MemoryAddrtrait as "MemoryAddr trait" Client ->> PageIterinstance: next() PageIterinstance ->> PageIterinstance: Check if start < end alt start < end PageIterinstance ->> PageIterinstance: Store current start as ret PageIterinstance ->> MemoryAddrtrait: start.add(PAGE_SIZE) MemoryAddrtrait -->> PageIterinstance: New start address PageIterinstance ->> PageIterinstance: Update self.start PageIterinstance -->> Client: Some(ret) else start >= end PageIterinstance -->> Client: None end
Sources: memory_addr/src/iter.rs(L50 - L65)
The iteration process:
- Boundary Check: Compare current
start
withend
- Value Return: If within bounds, return current
start
value - Advance: Increment
start
byPAGE_SIZE
using theadd
method - Termination: Return
None
whenstart
reaches or exceedsend
Usage Patterns
Basic Page Iteration
The most common usage pattern involves iterating over a memory range with 4KB pages:
// Example from documentation
let mut iter = PageIter::<0x1000, usize>::new(0x1000, 0x3000).unwrap();
assert_eq!(iter.next(), Some(0x1000));
assert_eq!(iter.next(), Some(0x2000));
assert_eq!(iter.next(), None);
Error Handling
PageIter construction can fail if alignment requirements are not met:
// This will return None due to misaligned end address
assert!(PageIter::<0x1000, usize>::new(0x1000, 0x3001).is_none());
Common PageIter Usage Scenarios
flowchart TD subgraph subGraph0["Common Page Sizes"] Page4K["0x1000 (4KB)"] Page2M["0x200000 (2MB)"] Page1G["0x40000000 (1GB)"] end PageIter["PageIter<PAGE_SIZE, A>"] Mapping["Memory Mapping Operations"] Allocation["Page Allocation"] Scanning["Memory Scanning"] Cleanup["Memory Cleanup"] MapPages["Map individual pages"] FindFree["Find free page sequences"] CheckPerms["Check page permissions"] UnmapPages["Unmap page ranges"] Allocation --> FindFree Cleanup --> UnmapPages Mapping --> MapPages PageIter --> Allocation PageIter --> Cleanup PageIter --> Mapping PageIter --> Page1G PageIter --> Page2M PageIter --> Page4K PageIter --> Scanning Scanning --> CheckPerms
Sources: memory_addr/src/iter.rs(L10 - L21)
Integration with Address Types
PageIter works with any type implementing MemoryAddr
, enabling type-safe iteration over different address spaces:
- Physical addresses:
PageIter<0x1000, PhysAddr>
- Virtual addresses:
PageIter<0x1000, VirtAddr>
- Raw addresses:
PageIter<0x1000, usize>
The iterator leverages the MemoryAddr
trait's is_aligned
and add
methods to ensure correct alignment validation and address arithmetic.
Sources: memory_addr/src/iter.rs(L1) memory_addr/src/iter.rs(L24) memory_addr/src/iter.rs(L32)