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
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn unmap(&mut self, vpn: VirtPageNum) {
|
||||||
|
self.page_table.unmap(vpn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// map area structure, controls a contiguous piece of virtual memory
|
/// map area structure, controls a contiguous piece of virtual memory
|
||||||
|
|
|
@ -13,7 +13,8 @@ mod memory_set;
|
||||||
mod page_table;
|
mod page_table;
|
||||||
|
|
||||||
pub use address::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum};
|
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 frame_allocator::{frame_alloc, FrameTracker};
|
||||||
pub use memory_set::remap_test;
|
pub use memory_set::remap_test;
|
||||||
pub use memory_set::{MapPermission, MemorySet, KERNEL_SPACE};
|
pub use memory_set::{MapPermission, MemorySet, KERNEL_SPACE};
|
||||||
|
|
|
@ -15,6 +15,8 @@ const SYSCALL_EXIT: usize = 93;
|
||||||
const SYSCALL_YIELD: usize = 124;
|
const SYSCALL_YIELD: usize = 124;
|
||||||
const SYSCALL_GET_TIME: usize = 169;
|
const SYSCALL_GET_TIME: usize = 169;
|
||||||
const SYSCALL_SBRK: usize = 214;
|
const SYSCALL_SBRK: usize = 214;
|
||||||
|
const SYSCALL_MMAP: usize = 222;
|
||||||
|
const SYSCALL_MUNMAP: usize = 215;
|
||||||
|
|
||||||
mod fs;
|
mod fs;
|
||||||
mod process;
|
mod process;
|
||||||
|
@ -30,6 +32,8 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||||
SYSCALL_YIELD => sys_yield(),
|
SYSCALL_YIELD => sys_yield(),
|
||||||
SYSCALL_GET_TIME => sys_get_time(),
|
SYSCALL_GET_TIME => sys_get_time(),
|
||||||
SYSCALL_SBRK => sys_sbrk(args[0] as i32),
|
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),
|
_ => panic!("Unsupported syscall_id: {}", syscall_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
//! Process management syscalls
|
//! 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;
|
use crate::timer::get_time_ms;
|
||||||
|
|
||||||
/// task exits and submit an exit code
|
/// task exits and submit an exit code
|
||||||
|
@ -29,3 +31,47 @@ pub fn sys_sbrk(size: i32) -> isize {
|
||||||
-1
|
-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;
|
mod task;
|
||||||
|
|
||||||
use crate::loader::{get_app_data, get_num_app};
|
use crate::loader::{get_app_data, get_num_app};
|
||||||
|
use crate::mm::{MapPermission, PageTableEntry, VirtAddr, VirtPageNum};
|
||||||
use crate::sbi::shutdown;
|
use crate::sbi::shutdown;
|
||||||
use crate::sync::UPSafeCell;
|
use crate::sync::UPSafeCell;
|
||||||
use crate::trap::TrapContext;
|
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> {
|
pub fn change_program_brk(size: i32) -> Option<usize> {
|
||||||
TASK_MANAGER.change_current_program_brk(size)
|
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);
|
||||||
|
}
|
||||||
|
|
33
user/src/bin/ch4_mmap0.rs
Normal file
33
user/src/bin/ch4_mmap0.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::mmap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
理想结果:输出 Test 04_1 OK!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn main() -> i32 {
|
||||||
|
let start: usize = 0x10000000;
|
||||||
|
let len: usize = 4096;
|
||||||
|
let prot: usize = 3;
|
||||||
|
assert_eq!(0, mmap(start, len, prot));
|
||||||
|
for i in start..(start + len) {
|
||||||
|
let addr: *mut u8 = i as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
*addr = i as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in start..(start + len) {
|
||||||
|
let addr: *mut u8 = i as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
assert_eq!(*addr, i as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Test 04_1 OK!");
|
||||||
|
0
|
||||||
|
}
|
25
user/src/bin/ch4_mmap1.rs
Normal file
25
user/src/bin/ch4_mmap1.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::mmap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
理想结果:程序触发访存异常,被杀死。不输出 error 就算过。
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn main() -> i32 {
|
||||||
|
let start: usize = 0x10000000;
|
||||||
|
let len: usize = 4096;
|
||||||
|
let prot: usize = 1;
|
||||||
|
assert_eq!(0, mmap(start, len, prot));
|
||||||
|
let addr: *mut u8 = start as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
*addr = start as u8;
|
||||||
|
}
|
||||||
|
println!("Should cause error, Test 04_2 fail!");
|
||||||
|
0
|
||||||
|
}
|
26
user/src/bin/ch4_mmap2.rs
Normal file
26
user/src/bin/ch4_mmap2.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::mmap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
理想结果:程序触发访存异常,被杀死。不输出 error 就算过。
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn main() -> i32 {
|
||||||
|
let start: usize = 0x10000000;
|
||||||
|
let len: usize = 4096;
|
||||||
|
let prot: usize = 2;
|
||||||
|
assert_eq!(0, mmap(start, len, prot));
|
||||||
|
let addr: *mut u8 = start as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
// *addr = start as u8; // can't write, R == 0 && W == 1 is illegal in riscv
|
||||||
|
assert!(*addr != 0);
|
||||||
|
}
|
||||||
|
println!("Should cause error, Test 04_2 fail!");
|
||||||
|
0
|
||||||
|
}
|
25
user/src/bin/ch4_mmap3.rs
Normal file
25
user/src/bin/ch4_mmap3.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::mmap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
理想结果:对于错误的 mmap 返回 -1,最终输出 Test 04_4 test OK!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn main() -> i32 {
|
||||||
|
let start: usize = 0x10000000;
|
||||||
|
let len: usize = 4096;
|
||||||
|
let prot: usize = 3;
|
||||||
|
assert_eq!(0, mmap(start, len, prot));
|
||||||
|
assert_eq!(mmap(start - len, len + 1, prot), -1);
|
||||||
|
assert_eq!(mmap(start + len + 1, len, prot), -1);
|
||||||
|
assert_eq!(mmap(start + len, len, 0), -1);
|
||||||
|
assert_eq!(mmap(start + len, len, prot | 8), -1);
|
||||||
|
println!("Test 04_4 test OK!");
|
||||||
|
0
|
||||||
|
}
|
36
user/src/bin/ch4_unmap.rs
Normal file
36
user/src/bin/ch4_unmap.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::{mmap, munmap};
|
||||||
|
|
||||||
|
/*
|
||||||
|
理想结果:输出 Test 04_5 ummap OK!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn main() -> i32 {
|
||||||
|
let start: usize = 0x10000000;
|
||||||
|
let len: usize = 4096;
|
||||||
|
let prot: usize = 3;
|
||||||
|
assert_eq!(0, mmap(start, len, prot));
|
||||||
|
assert_eq!(mmap(start + len, len * 2, prot), 0);
|
||||||
|
assert_eq!(munmap(start, len), 0);
|
||||||
|
assert_eq!(mmap(start - len, len + 1, prot), 0);
|
||||||
|
for i in (start - len)..(start + len * 3) {
|
||||||
|
let addr: *mut u8 = i as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
*addr = i as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in (start - len)..(start + len * 3) {
|
||||||
|
let addr: *mut u8 = i as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
assert_eq!(*addr, i as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Test 04_5 ummap OK!");
|
||||||
|
0
|
||||||
|
}
|
23
user/src/bin/ch4_unmap2.rs
Normal file
23
user/src/bin/ch4_unmap2.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::{mmap, munmap};
|
||||||
|
|
||||||
|
/*
|
||||||
|
理想结果:输出 Test 04_6 ummap2 OK!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn main() -> i32 {
|
||||||
|
let start: usize = 0x10000000;
|
||||||
|
let len: usize = 4096;
|
||||||
|
let prot: usize = 3;
|
||||||
|
assert_eq!(0, mmap(start, len, prot));
|
||||||
|
assert_eq!(munmap(start, len + 1), -1);
|
||||||
|
assert_eq!(munmap(start + 1, len - 1), -1);
|
||||||
|
println!("Test 04_6 ummap2 OK!");
|
||||||
|
0
|
||||||
|
}
|
47
user/src/bin/ch4b_sbrk.rs
Normal file
47
user/src/bin/ch4b_sbrk.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::sbrk;
|
||||||
|
use core::ptr::slice_from_raw_parts_mut;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn main() -> i32 {
|
||||||
|
println!("Test sbrk start.");
|
||||||
|
const PAGE_SIZE: usize = 0x1000;
|
||||||
|
let origin_brk = sbrk(0);
|
||||||
|
println!("origin break point = {:x}", origin_brk);
|
||||||
|
let brk = sbrk(PAGE_SIZE as i32);
|
||||||
|
if brk != origin_brk {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
let brk = sbrk(0);
|
||||||
|
println!("one page allocated, break point = {:x}", brk);
|
||||||
|
println!("try write to allocated page");
|
||||||
|
let new_page = unsafe { &mut *slice_from_raw_parts_mut(origin_brk as usize as *const u8 as *mut u8, PAGE_SIZE) };
|
||||||
|
for pos in 0..PAGE_SIZE {
|
||||||
|
new_page[pos] = 1;
|
||||||
|
}
|
||||||
|
println!("write ok");
|
||||||
|
sbrk(PAGE_SIZE as i32 * 10);
|
||||||
|
let brk = sbrk(0);
|
||||||
|
println!("10 page allocated, break point = {:x}", brk);
|
||||||
|
sbrk(PAGE_SIZE as i32 * -11);
|
||||||
|
let brk = sbrk(0);
|
||||||
|
println!("11 page DEALLOCATED, break point = {:x}", brk);
|
||||||
|
println!("try DEALLOCATED more one page, should be failed.");
|
||||||
|
let ret = sbrk(PAGE_SIZE as i32 * -1);
|
||||||
|
if ret != -1 {
|
||||||
|
println!("Test sbrk failed!");
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
println!("Test sbrk almost OK!");
|
||||||
|
println!("now write to deallocated page, should cause page fault.");
|
||||||
|
for pos in 0..PAGE_SIZE {
|
||||||
|
new_page[pos] = 2;
|
||||||
|
}
|
||||||
|
println!("Test sbrk failed!");
|
||||||
|
0
|
||||||
|
}
|
|
@ -38,3 +38,11 @@ pub fn get_time() -> isize {
|
||||||
pub fn sbrk(size: i32) -> isize {
|
pub fn sbrk(size: i32) -> isize {
|
||||||
sys_sbrk(size)
|
sys_sbrk(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn munmap(start: usize, len: usize) -> isize {
|
||||||
|
sys_munmap(start, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mmap(start: usize, len: usize, prot: usize) -> isize {
|
||||||
|
sys_mmap(start, len, prot)
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ const SYSCALL_EXIT: usize = 93;
|
||||||
const SYSCALL_YIELD: usize = 124;
|
const SYSCALL_YIELD: usize = 124;
|
||||||
const SYSCALL_GET_TIME: usize = 169;
|
const SYSCALL_GET_TIME: usize = 169;
|
||||||
const SYSCALL_SBRK: usize = 214;
|
const SYSCALL_SBRK: usize = 214;
|
||||||
|
pub const SYSCALL_MMAP: usize = 222;
|
||||||
|
pub const SYSCALL_MUNMAP: usize = 215;
|
||||||
|
|
||||||
fn syscall(id: usize, args: [usize; 3]) -> isize {
|
fn syscall(id: usize, args: [usize; 3]) -> isize {
|
||||||
let mut ret: isize;
|
let mut ret: isize;
|
||||||
|
@ -39,3 +41,11 @@ pub fn sys_get_time() -> isize {
|
||||||
pub fn sys_sbrk(size: i32) -> isize {
|
pub fn sys_sbrk(size: i32) -> isize {
|
||||||
syscall(SYSCALL_SBRK, [size as usize, 0, 0])
|
syscall(SYSCALL_SBRK, [size as usize, 0, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sys_mmap(start: usize, len: usize, prot: usize) -> isize {
|
||||||
|
syscall(SYSCALL_MMAP, [start, len, prot])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sys_munmap(start: usize, len: usize) -> isize {
|
||||||
|
syscall(SYSCALL_MUNMAP, [start, len, 0])
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue