lab-04: mmap, munmap
This commit is contained in:
parent
eaacb4fa25
commit
cc1a9a4751
14 changed files with 311 additions and 2 deletions
|
@ -266,6 +266,9 @@ impl MemorySet {
|
|||
false
|
||||
}
|
||||
}
|
||||
pub fn unmap(&mut self, vpn: VirtPageNum) {
|
||||
self.page_table.unmap(vpn)
|
||||
}
|
||||
}
|
||||
|
||||
/// map area structure, controls a contiguous piece of virtual memory
|
||||
|
|
|
@ -13,7 +13,8 @@ mod memory_set;
|
|||
mod page_table;
|
||||
|
||||
pub use address::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum};
|
||||
use address::{StepByOne, VPNRange};
|
||||
use address::StepByOne;
|
||||
pub use address::VPNRange;
|
||||
pub use frame_allocator::{frame_alloc, FrameTracker};
|
||||
pub use memory_set::remap_test;
|
||||
pub use memory_set::{MapPermission, MemorySet, KERNEL_SPACE};
|
||||
|
|
|
@ -15,6 +15,8 @@ const SYSCALL_EXIT: usize = 93;
|
|||
const SYSCALL_YIELD: usize = 124;
|
||||
const SYSCALL_GET_TIME: usize = 169;
|
||||
const SYSCALL_SBRK: usize = 214;
|
||||
const SYSCALL_MMAP: usize = 222;
|
||||
const SYSCALL_MUNMAP: usize = 215;
|
||||
|
||||
mod fs;
|
||||
mod process;
|
||||
|
@ -30,6 +32,8 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
|||
SYSCALL_YIELD => sys_yield(),
|
||||
SYSCALL_GET_TIME => sys_get_time(),
|
||||
SYSCALL_SBRK => sys_sbrk(args[0] as i32),
|
||||
SYSCALL_MMAP => sys_mmap(args[0], args[1], args[2]),
|
||||
SYSCALL_MUNMAP => sys_munmap(args[0], args[1]),
|
||||
_ => panic!("Unsupported syscall_id: {}", syscall_id),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Process management syscalls
|
||||
|
||||
use crate::task::{change_program_brk, exit_current_and_run_next, suspend_current_and_run_next};
|
||||
use crate::config::PAGE_SIZE;
|
||||
use crate::mm::{MapPermission, VPNRange, VirtAddr};
|
||||
use crate::task::{change_program_brk, create_new_map_area, exit_current_and_run_next, get_current_task_page_table_entry, suspend_current_and_run_next, unmap_virtual_page};
|
||||
use crate::timer::get_time_ms;
|
||||
|
||||
/// task exits and submit an exit code
|
||||
|
@ -29,3 +31,47 @@ pub fn sys_sbrk(size: i32) -> isize {
|
|||
-1
|
||||
}
|
||||
}
|
||||
|
||||
/// map files or devices into memory
|
||||
pub fn sys_mmap(start: usize, len: usize, prot: usize) -> isize {
|
||||
if start % PAGE_SIZE != 0 || prot & !0x7 != 0 || prot & 0x7 == 0 {
|
||||
return -1;
|
||||
}
|
||||
let vpn_start = VirtAddr::from(start).floor();
|
||||
let vpn_end = VirtAddr::from(start + len).ceil();
|
||||
let vpn_range = VPNRange::new(vpn_start, vpn_end);
|
||||
for vpn in vpn_range {
|
||||
if let Some(pte) = get_current_task_page_table_entry(vpn) {
|
||||
if pte.is_valid() {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
create_new_map_area(
|
||||
vpn_start.into(),
|
||||
vpn_end.into(),
|
||||
MapPermission::from_bits_truncate((prot << 1) as u8) | MapPermission::U
|
||||
);
|
||||
0
|
||||
}
|
||||
|
||||
/// unmap files or devices into memory
|
||||
pub fn sys_munmap(start: usize, len: usize) -> isize {
|
||||
if start % PAGE_SIZE != 0 {
|
||||
return -1;
|
||||
}
|
||||
let vpn_start = VirtAddr::from(start).floor();
|
||||
let vpn_end = VirtAddr::from(start + len).ceil();
|
||||
let vpn_range = VPNRange::new(vpn_start, vpn_end);
|
||||
for vpn in vpn_range {
|
||||
if let Some(pte) = get_current_task_page_table_entry(vpn) {
|
||||
if !pte.is_valid() {
|
||||
return -1;
|
||||
}
|
||||
unmap_virtual_page(vpn)
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ mod switch;
|
|||
mod task;
|
||||
|
||||
use crate::loader::{get_app_data, get_num_app};
|
||||
use crate::mm::{MapPermission, PageTableEntry, VirtAddr, VirtPageNum};
|
||||
use crate::sbi::shutdown;
|
||||
use crate::sync::UPSafeCell;
|
||||
use crate::trap::TrapContext;
|
||||
|
@ -204,3 +205,24 @@ pub fn current_trap_cx() -> &'static mut TrapContext {
|
|||
pub fn change_program_brk(size: i32) -> Option<usize> {
|
||||
TASK_MANAGER.change_current_program_brk(size)
|
||||
}
|
||||
|
||||
/// Get the curent 'Running' task's PTE
|
||||
pub fn get_current_task_page_table_entry(vpn: VirtPageNum) -> Option<PageTableEntry> {
|
||||
let inner = TASK_MANAGER.inner.exclusive_access();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].memory_set.translate(vpn)
|
||||
}
|
||||
|
||||
/// create new mapping area
|
||||
pub fn create_new_map_area(start_va: VirtAddr, end_va: VirtAddr, perm: MapPermission) {
|
||||
let mut inner = TASK_MANAGER.inner.exclusive_access();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].memory_set.insert_framed_area(start_va, end_va, perm);
|
||||
}
|
||||
|
||||
/// unmap virtual page
|
||||
pub fn unmap_virtual_page(vpn: VirtPageNum) {
|
||||
let mut inner = TASK_MANAGER.inner.exclusive_access();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].memory_set.unmap(vpn);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue