MmStruct

Struct MmStruct 

Source
pub struct MmStruct<P: Pager> {
    pub page_table: PageTable,
    pub pager: P,
}
Expand description

The MmStruct represents the memory state for a specific process, corresponding to the Linux kernel’s struct mm_struct.

This struct encapsulates the essential information required to manage a process’s virtual memory, including its page table and the pager responsible for handling memory mapping operations (such as mmap and munmap).

The MmStruct ensures that memory-related system calls and operations are correctly applied within the process’s address space. It provides mechanisms to allocate, map, and unmap memory pages, and serves as the interface through which the OS kernel interacts with the user process’s memory layout.

§Memory State

The memory state includes the page table (referenced by page_table_addr) that manages the virtual-to-physical address translations for the process, and a pager (pager) that defines how memory-mapped files and dynamic memory allocations are handled. Together, these components allow each process to maintain its own isolated memory environment, supporting both memory protection and efficient address space management.

Like its Linux counterpart, MmStruct plays a central role in memory management, providing the kernel with per-process control over virtual memory.

Fields§

§page_table: PageTable

The page table that maintains mappings between virtual and physical addresses.

§pager: P

The pager that handles memory allocation (mmap) and deallocation (munmap).

Implementations§

Source§

impl<P: Pager> MmStruct<P>

Source

pub fn new() -> Self

Creates a new MmStruct with an empty page table and a new pager instance.

§Returns
Source

pub fn access_ok(&self, addr: Range<Va>, is_write: bool) -> bool

This function ensures that system calls using memory addresses (such as read, write, etc.) operate only on valid and accessible memory regions.

§Parameters
  • addr: A range of virtual addresses to be accessed.
  • is_write: true if the memory is being written to, false if it’s only being read.
§Returns
  • true if the memory range is valid.
  • false if the memory range is invalid or inaccessible.
Source

pub fn do_mmap( &mut self, addr: Va, size: usize, prot: Permission, file: Option<&RegularFile>, offset: usize, ) -> Result<usize, KernelError>

Wrapper function for the pager’s mmap method. It delegates the actual memory mapping operation to the pager’s mmap method.

§Parameters
  • fstate: A mutable reference to the file state.
  • abi: The system call ABI, which contains the arguments for the system call.
§Returns
  • The result of the memory mapping operation, returned by the pager’s mmap.
Source

pub fn mmap( &mut self, fstate: &mut FileStruct, abi: &SyscallAbi<'_>, ) -> Result<usize, KernelError>

Maps a file into the process’s virtual address space.

This function implements the mmap system call, which maps either an anonymous mapping (fd = -1) or portion of a file into memory (fd >= 0). If the mapped region represent a file content, user programs can access the file contents as the part of the process’s memory.

§Syscall API
void *mmap(void *addr, size_t length, int prot, int fd, off_t offset);
  • addr: Desired starting address of the mapping (must be page-aligned and non-zero).
  • length: Number of bytes to map (must be non-zero).
  • prot: Desired memory protection flags.
  • fd: File descriptor of the file to be mapped.
  • offset: Offset in the file where mapping should begin.
§Arguments
  • fstate - Mutable reference to the current file state.
  • abi - A reference to the system call arguments, including the file descriptor, mapping length, protection flags, and file offset.
§Behavior

This function performs validation on the provided arguments before forwarding the request to the pager’s mmap method. The following conditions must be met:

  • addr must be non-zero and page-aligned.
  • length must be non-zero.
  • The file descriptor must refer to a regular file or -1 for anonymous mapping.
  • The mapping must not overlap with any already mapped region, including the user stack or any memory occupied by the program binary.

Unlike Linux, KeOS does not support automatic address selection for addr == NULL, so mmap fails if addr is zero.

If the length of the file is not a multiple of the page size, any excess bytes in the final page are zero-filled.

§Returns

Returns the starting virtual address of the mapped region on success, or a KernelError on failure due to invalid arguments or conflicts with existing memory mappings.

Source

pub fn munmap(&mut self, abi: &SyscallAbi<'_>) -> Result<usize, KernelError>

Unmaps a memory-mapped file region.

This function implements the munmap system call, which removes a previously established memory mapping created by mmap. It releases the virtual memory associated with the mapping.

§Syscall API
int munmap(void *addr);
  • addr: The starting virtual address of the mapping to unmap. This must match the address returned by a previous call to mmap by the same process and must not have been unmapped already.
§Arguments
  • fstate - Mutable reference to the current file state.
  • abi - A reference to the system call arguments, including the address to unmap.
§Behavior
  • Unmaps the virtual memory region starting at addr that was previously mapped via mmap.
  • Unmodified pages are simply discarded.
  • The virtual pages corresponding to the mapping are removed from the process’s address space.
§Additional Notes
  • Calling close on a file descriptor or removing the file from the filesystem does not unmap any of its active mappings.
  • To follow the Unix convention, mappings remain valid until they are explicitly unmapped via munmap.
§Returns

Returns Ok(0) on success or a KernelError if the address is invalid or does not correspond to an active memory mapping.

Source

pub fn get_user_page_and<R>( &mut self, addr: Va, f: impl FnOnce(PageRef<'_>, Permission) -> R, ) -> Result<R, KernelError>

Find a mapped page at the given virtual address and apply a function to it.

This function searches for a memory page mapped at addr and, if found, applies the provided function f to it. The function f receives a PageRef to the page and its corresponding Permission flags.

§Parameters
  • addr: The virtual address (Va) of the page to find.
  • f: A closure that takes a PageRef and its Permission flags, returning a value of type R.
§Returns
  • Some(R): If the page is found, the function f is applied, and its result is returned.
  • None: If no mapped page is found at addr.
§Usage

This method allows safe access to a mapped page. It is useful for performing read operations or permission checks on a page.

§Safety
  • The rust’s lifetime guarantees that the closure f never stores the PageRef beyond its invocation.

Trait Implementations§

Source§

impl<P: Pager> Default for MmStruct<P>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<P> Freeze for MmStruct<P>
where P: Freeze,

§

impl<P> RefUnwindSafe for MmStruct<P>
where P: RefUnwindSafe,

§

impl<P> Send for MmStruct<P>
where P: Send,

§

impl<P> Sync for MmStruct<P>
where P: Sync,

§

impl<P> Unpin for MmStruct<P>
where P: Unpin,

§

impl<P> UnwindSafe for MmStruct<P>
where P: UnwindSafe,

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.