From 3e5dc6dbd98cd1648ff7c29f3ed21f7bb7872e2e Mon Sep 17 00:00:00 2001
From: plc02 <1415227972@qq.com>
Date: Thu, 27 Mar 2025 19:45:05 +0800
Subject: [PATCH] mmap,munmap

---
 os/src/config.rs          |   3 +-
 os/src/main.rs            |   2 +-
 os/src/mm/memory_set.rs   |  79 +++++++++++++++++---
 os/src/syscall/fs.rs      | 152 +++++++++++++++++++++++++++++++++++++-
 os/src/syscall/mod.rs     |  12 ++-
 os/src/syscall/process.rs |  72 +++++-------------
 os/src/task/mod.rs        |   2 +-
 os/src/task/task.rs       |  65 +++++++++++++++-
 user/src/bin/brktest.rs   |   2 +-
 user/src/bin/mmap.rs      |  12 +++
 user/src/bin/rwo.rs       |  58 +++++++++++++++
 vfs-defs/src/file.rs      |   2 +-
 12 files changed, 384 insertions(+), 77 deletions(-)
 create mode 100644 user/src/bin/mmap.rs
 create mode 100644 user/src/bin/rwo.rs

diff --git a/os/src/config.rs b/os/src/config.rs
index 5f0298f..1847b66 100644
--- a/os/src/config.rs
+++ b/os/src/config.rs
@@ -6,7 +6,8 @@ use crate::task::Utsname;
 pub const USER_STACK_SIZE: usize = 4096 * 5;
 pub const KERNEL_STACK_SIZE: usize = 4096 *10;
 pub const KERNEL_HEAP_SIZE: usize = 0x200_0000;
-
+pub const USER_STACK_TOP: usize = 0x8000_0000;
+pub const USER_MMAP_TOP: usize = 0x6000_0000;
 pub const PAGE_SIZE: usize = 0x1000;
 #[allow(unused)]
 pub const USER_HEAP_SIZE: usize = 32768;
diff --git a/os/src/main.rs b/os/src/main.rs
index 91dceb2..11fe391 100644
--- a/os/src/main.rs
+++ b/os/src/main.rs
@@ -116,7 +116,7 @@ impl ArchInterface for ArchInterfaceImpl {
                 let args = ctx.args();
                 // get system call return value
                 // info!("syscall: {}", ctx[TrapFrameArgs::SYSCALL]);
-                let result = syscall(ctx[TrapFrameArgs::SYSCALL], [args[0], args[1], args[2],args[3],args[4]]);
+                let result = syscall(ctx[TrapFrameArgs::SYSCALL], [args[0], args[1], args[2],args[3],args[4],args[5]]);
                 // cx is changed during sys_exec, so we have to call it again
                 ctx[TrapFrameArgs::RET] = result as usize;
             }
diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs
index 4e26ee8..94b08b0 100644
--- a/os/src/mm/memory_set.rs
+++ b/os/src/mm/memory_set.rs
@@ -7,7 +7,7 @@ use alloc::alloc::dealloc;
 use arch::pagetable::{MappingFlags, MappingSize, PageTable, PageTableWrapper};
 use arch::addr::{PhysAddr, PhysPage, VirtAddr, VirtPage};
 use arch::USER_VADDR_END;
-use crate::config::{PAGE_SIZE, USER_STACK_SIZE};
+use crate::config::{PAGE_SIZE, USER_STACK_SIZE, USER_STACK_TOP, USER_MMAP_TOP};
 use crate::sync::UPSafeCell;
 use alloc::collections::BTreeMap;
 use alloc::sync::Arc;
@@ -35,7 +35,9 @@ pub struct MemorySet {
     ///
     pub areas: Vec<MapArea>,
     ///
-    pub heap_area: MapArea,
+    pub heap_area: Vec<MapArea>,
+    ///
+    pub mmap_area: Vec<MapArea>,
 }
 
 impl MemorySet {
@@ -44,12 +46,8 @@ impl MemorySet {
         Self {
             page_table:Arc::new(PageTableWrapper::alloc()),
             areas: Vec::new(),
-            heap_area: MapArea::new( 
-            VirtAddr::new(0),
-            VirtAddr::new(0),
-            crate::mm::MapType::Framed,
-            MapPermission::U | MapPermission::R | MapPermission::W |MapPermission::X,
-            ),
+            heap_area: Vec::new(),
+            mmap_area: Vec::new(),
         }
     }
     ///Get pagetable `root_ppn`
@@ -64,6 +62,22 @@ impl MemorySet {
         }
         self.areas.push(map_area);
     }
+    /// 分配+映射->heap_area
+    pub fn push_into_heaparea(&mut self, mut map_area: MapArea, data: Option<&[u8]>) { 
+        map_area.map(&self.page_table);
+        if let Some(data) = data {
+            map_area.copy_data(&self.page_table, data);
+        }
+        self.heap_area.push(map_area);
+    }
+    /// 分配+映射->mmap_area
+    pub fn push_into_mmaparea(&mut self, mut map_area: MapArea, data: Option<&[u8]>) {
+        map_area.map(&self.page_table);
+        if let Some(data) = data {
+            map_area.copy_data(&self.page_table, data);
+        }
+        self.mmap_area.push(map_area);
+    }
     /// Include sections in elf and trampoline and TrapContext and user stack,
     /// also returns user_sp and entry point.
     pub fn from_elf(elf_data: &[u8]) -> (Self, usize, usize, usize) {
@@ -114,7 +128,7 @@ impl MemorySet {
         // let max_end_va: VirtAddr = max_end_vpn.into();
         
         // guard page
-        let user_stack_top = 0x8000_0000;
+        let user_stack_top = USER_STACK_TOP; //8G
         let user_stack_bottom = user_stack_top - USER_STACK_SIZE;
         //println!("heaptop:{:x} user_stack_bottom:{:x}",heap_top,user_stack_top);
         memory_set.push(
@@ -151,6 +165,35 @@ impl MemorySet {
                   dst_ppn.get_buffer().copy_from_slice(src_ppn.get_buffer())
             }
         }
+        // copy heap_area (可能出错)
+        for area in user_space.heap_area.iter() {
+            let new_area = MapArea::from_another(area);
+            memory_set.push_into_heaparea(new_area, None);
+            // copy data from another space
+            for vpn in area.vpn_range {
+                let src_ppn = user_space.translate(vpn).unwrap().0;
+                let dst_ppn = memory_set.translate(vpn).unwrap().0;
+              //  dst_ppn
+                //    .get_bytes_array()
+                  //  .copy_from_slice(src_ppn.get_bytes_array());
+                  dst_ppn.get_buffer().copy_from_slice(src_ppn.get_buffer())
+            }
+        }
+        //copy mmap_area (可能出错)
+        for area in user_space.mmap_area.iter() {
+            let new_area = MapArea::from_another(area);
+            memory_set.push_into_mmaparea(new_area, None);
+            // copy data from another space
+            for vpn in area.vpn_range {
+                let src_ppn = user_space.translate(vpn).unwrap().0;
+                let dst_ppn = memory_set.translate(vpn).unwrap().0;
+              //  dst_ppn
+                //    .get_bytes_array()
+                  //  .copy_from_slice(src_ppn.get_bytes_array());
+                  dst_ppn.get_buffer().copy_from_slice(src_ppn.get_buffer())
+            }
+        }
+        
         memory_set
     }
     ///Refresh TLB with `sfence.vma`
@@ -168,7 +211,18 @@ impl MemorySet {
         //*self = Self::new_bare();
         self.areas.clear();
     }
+    /// 用于munmap
+    pub fn remove_map_area_by_vpn_start(&mut self, num: VirtPage) -> i32 {
+        if let Some(pos) = self.mmap_area.iter().position(|map_area| map_area.vpn_range.get_start() == num) {
+            println!("remove vpn: {}~{}",self.mmap_area[pos].vpn_range.get_start(),self.mmap_area[pos].vpn_range.get_end());
+            self.mmap_area.remove(pos);
+            0 // 成功找到并移除,返回 0 或其他表示成功的值
+        } else {
+            -1 // 未找到,返回 -1 或其他表示失败的值
+        }
+    }
 }
+/*
 // 动态堆
 impl MemorySet {
     /// 映射虚拟页号到物理页帧
@@ -221,7 +275,7 @@ impl MemorySet {
     }
         //frame_dealloc(ppn);
         //还需要对area做data_frames.remove(&ppn);
-}
+}*/
 
 /// map area structure, controls a contiguous piece of virtual memory
 
@@ -294,8 +348,9 @@ impl MapArea {
         for vpn in self.vpn_range {
             //self.map_one(page_table, vpn);
             let p_tracker = frame_alloc().expect("can't allocate frame");
+            //println!("vpn={},ppn={}",vpn,p_tracker.ppn);
             page_table.map_page(vpn, p_tracker.ppn, self.map_perm.into(), MappingSize::Page4KB);
-            self.data_frames.insert(p_tracker.ppn, p_tracker);
+            self.data_frames.insert(p_tracker.ppn, p_tracker);   
         }
     } /* 
     pub fn unmap(&mut self, page_table: &mut PageTable) {
@@ -341,7 +396,7 @@ bitflags! {
         const R = 1 << 1;
         ///Writable
         const W = 1 << 2;
-        ///Excutable
+        ///Executable
         const X = 1 << 3;
         ///Accessible in U mode
         const U = 1 << 4;
diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs
index 6be8b2b..188ece3 100644
--- a/os/src/syscall/fs.rs
+++ b/os/src/syscall/fs.rs
@@ -1,12 +1,15 @@
 //! File and filesystem-related syscalls
+use crate::config::USER_STACK_TOP;
 use crate::fs::{open_file,create_file};
 use crate::fs::make_pipe;
 use crate::fs::path_to_dentry;
 use crate::fs::path_to_father_dentry;
 use crate::mm::{translated_refmut,translated_byte_buffer, translated_str};
-use crate::task::{current_task, current_user_token};
+use crate::task::{current_task, current_user_token, MapFdControl};
 use alloc::string::String;
 
+use arch::addr::{VirtAddr, VirtPage};
+use arch::PAGE_SIZE;
 use device::BLOCK_DEVICE;
 use vfs_defs::Kstat;
 use vfs_defs::MountFlags;
@@ -21,7 +24,9 @@ use crate::mm::frame_dealloc;
 use crate::mm::MapType;
 use alloc::sync::Arc;
 use alloc::vec::Vec;
-use core::ptr;
+use core::ptr::{self, addr_of_mut, null_mut};
+use core::slice;
+use alloc::vec;
 
 //const HEAP_MAX: usize = 0;
 pub const AT_FDCWD: isize = -100;
@@ -44,12 +49,14 @@ pub fn sys_write(fd: usize, buf: *mut u8, len: usize) -> isize {
         // release current task TCB manually to avoid multi-borrow
         drop(inner);
         file.write(translated_byte_buffer(token, buf, len)) as isize
-    } else {
+    }
+     else {
         println!("write3");
         -1
     }
 }
 
+
 pub fn sys_read(fd: usize, buf: *mut u8, len: usize) -> isize {
     let token = current_user_token();
     let task = current_task().unwrap();
@@ -308,4 +315,143 @@ pub fn sys_fstat(fd:usize,kst:*mut Kstat)->isize{
         return 0;
     }
     return -1;
+}
+/*
+addr:
+指定映射被放置的虚拟地址,如果将addr指定为NULL,那么内核会为映射分配一个合适的地址。如果addr为一个非NULL值,
+则内核在选择地址映射时会将该参数值作为一个提示信息来处理。不管采用何种方式,内核会选择一个不与任何既有映射冲突的地
+址。在处理过程中, 内核会将指定的地址舍入到最近的一个分页边界处。
+length:
+参数指定了映射的字节数。尽管length 无需是一个系统分页大小的倍数,但内核会以分页大小为单位来创建映射,
+因此实际上length会被向上提升为分页大小的下一个倍数。
+prot: 映射的内存保护方式,可取:PROT_EXEC, PROT_READ, PROT_WRITE, PROT_NONE
+flags: 映射是否与其他进程共享的标志,
+fd: 文件句柄,
+off: 文件偏移量 =? (off,off+len)
+返回值:成功返回已映射区域的指针,失败返回-1;
+void *start, size_t len, int prot, int flags, int fd, off_t off
+long ret = syscall(SYS_mmap, start, len, prot, flags, fd, off);
+不需要实际分配物理地址
+*/
+pub fn sys_mmap(
+    _start: *mut usize,
+    len: usize,
+    _prot: i32,
+    _flags: i32,
+    fd: usize,
+    off: i32,
+) -> isize {
+    if len==0 || off!=0 {
+        return -1;
+    }
+    // 长度对齐
+    let mut num = len / PAGE_SIZE;//num:页数量
+    if num*PAGE_SIZE != len {
+        num = num + 1;
+    }
+    // 获取文件数据
+    let mut buf = vec![0u8; len];
+    let buf_ptr = buf.as_mut_ptr();
+
+    let task = current_task().unwrap();
+    let inner = task.inner_exclusive_access();
+    if fd >= inner.fd_table.len() {
+        return -1;
+    }
+    if let Some(file) = &inner.fd_table[fd] {
+        let file = file.clone();
+        if !file.readable() {
+            return -1;
+        }
+        // release current task TCB manually to avoid multi-borrow
+        drop(inner);
+        file.read_at(0, &mut buf);
+    } else {
+        return -1;
+    }
+    
+    let mut inner = task.inner_exclusive_access();
+    let mut start = inner.mapareacontrol.find_block(num);// num是需要的页数目 
+    let mut move_top = false;
+    if start == 0 {
+        start = inner.mapareacontrol.mmap_top;
+        move_top = true;
+    }
+    if len + start >= USER_STACK_TOP {
+        // 与栈重叠
+        return -1;
+    }
+    let start_va = VirtAddr::new(start);
+    let end_va = VirtAddr::new(start + len);
+
+    inner.memory_set.push_into_mmaparea(
+        MapArea::new(
+            start_va,
+            end_va,
+            MapType::Framed,
+        MapPermission::R|MapPermission::U|MapPermission::W|MapPermission::X
+        ),
+        unsafe {
+            Some(slice::from_raw_parts(buf_ptr, len))
+        }
+    );
+    if move_top {
+        inner.mapareacontrol.mmap_top += num * PAGE_SIZE;
+    }
+    inner.mapareacontrol.mapfd.push(
+        MapFdControl { 
+            fd: fd, 
+            len: len,
+            start_va: start
+        }
+    );
+    return start as isize;
+    
+}
+//void *start, size_t len
+//int ret = syscall(SYS_munmap, start, len);
+pub fn sys_munmap(start: *mut usize, _len: usize) -> isize {
+    if start as usize/ PAGE_SIZE *PAGE_SIZE != start as usize {
+        // 未对齐,地址错误
+        return -1;
+    }
+    let task = current_task().unwrap();
+    let mut inner = task.inner_exclusive_access();
+    if inner.mapareacontrol.mmap_top <= start as usize {
+        // 地址越界
+        return -2;
+    }
+    // fd
+    let mut len: usize = 0;
+    let fd = inner.mapareacontrol.find_fd(start as usize, &mut len);
+    if fd < 0 {
+        println!("fd not found!");
+        return -3;
+    }
+    if fd >= inner.fd_table.len() as isize {
+        println!("fd out of range!");
+        return -4;
+    }
+    // read data from va
+    let mut buf = vec![0u8; len];
+    
+    if let Some(file) = &inner.fd_table[fd as usize] {
+        let file = file.clone();
+        if !file.writable() {
+            return -5;
+        }
+        // release current task TCB manually to avoid multi-borrow
+        drop(inner);
+        file.write_at(0, &mut buf);
+    } else {
+        return -6;
+    }
+    let mut inner = task.inner_exclusive_access();
+    let res = inner.memory_set.remove_map_area_by_vpn_start(VirtAddr::new(start as usize).into());
+    if res < 0 {
+        // 找不到地址
+        println!("vpn not found!");
+        return -7;
+    }
+    0
 }
\ No newline at end of file
diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs
index 5eefbd8..7820d46 100644
--- a/os/src/syscall/mod.rs
+++ b/os/src/syscall/mod.rs
@@ -32,8 +32,10 @@ const SYSCALL_UNAME: usize = 160;
 const SYSCALL_GET_TIME: usize = 169;
 const SYSCALL_GETPID: usize = 172;
 const SYSCALL_BRK: usize = 214;
+const SYSCALL_MUNMAP: usize = 215;
 const SYSCALL_FORK: usize = 220;
 const SYSCALL_EXEC: usize = 221;
+const SYSCALL_MMAP: usize = 222;
 const SYSCALL_WAITPID: usize = 260;
 
 mod fs;
@@ -45,7 +47,7 @@ use crate::task::{Tms, Utsname};
 const MODULE_LEVEL:log::Level = log::Level::Trace;
 
 /// handle syscall exception with `syscall_id` and other arguments
-pub fn syscall(syscall_id: usize, args: [usize; 5]) -> isize {
+pub fn syscall(syscall_id: usize, args: [usize; 6]) -> isize {
    // println!("syscallid:{}",syscall_id);
     let mut result:isize = 0;
     match syscall_id {
@@ -150,6 +152,14 @@ pub fn syscall(syscall_id: usize, args: [usize; 5]) -> isize {
             result = sys_uname(args[0] as *mut Utsname);
             log_debug!("syscall_uname result:{}",result);
         }
+        SYSCALL_MMAP => {
+            result = sys_mmap(args[0] as *mut usize, args[1], args[2] as i32, args[3] as i32, args[4],args[5] as i32);
+            log_debug!("syscall_mmap result:{}",result);
+        }
+        SYSCALL_MUNMAP => {
+            result = sys_munmap(args[0] as *mut usize, args[1]);
+            log_debug!("syscall_munmap result:{}",result);
+        }
         _ => panic!("Unsupported syscall_id: {}", syscall_id),
     }
     result
diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs
index bf3fac4..ae1cf6d 100644
--- a/os/src/syscall/process.rs
+++ b/os/src/syscall/process.rs
@@ -1,5 +1,5 @@
 use crate::fs::{open_file,path_to_dentry,path_to_father_dentry,create_file};
-use crate::mm::{translated_refmut, translated_str,translated_ref};
+use crate::mm::{translated_ref, translated_refmut, translated_str, MapType};
 use crate::task::{
     add_task, current_task, current_user_token, exit_current_and_run_next,
     suspend_current_and_run_next,
@@ -13,7 +13,7 @@ use crate::drivers::BLOCK_DEVICE;
 use vfs_defs::{DiskInodeType,OpenFlags,Dentry};
 use crate::config::{PAGE_SIZE, UNAME};
 use arch::addr::{PhysPage, VirtAddr, VirtPage};
-use crate::mm::MapPermission;
+use crate::mm::{MapPermission, MapArea};
 use arch::pagetable::MappingSize;
 use crate::task::{Tms, Utsname};
 
@@ -203,67 +203,31 @@ pub fn sys_brk(new_brk:  usize) -> isize {
         task_inner.heap_top = new_brk;
         return 0;
     }
-    
-    let mut need_align: bool = false;
-    // new_brk->align to 4K
-    let num = new_brk / PAGE_SIZE;
-    if num*PAGE_SIZE < new_brk {
-        //align_brk = (num + 1)*PAGE_SIZE;
-        need_align = true;
-    }
 
     if new_brk > cur_brk {
         let user_stack_bottom = task_inner.stack_bottom;
         
-        if new_brk >= user_stack_bottom { 
+        if new_brk >= user_stack_bottom -PAGE_SIZE { 
             return -1;
         }
-        // 确认新增虚拟页号范围
-        //let cur_page = (cur_brk + PAGE_SIZE - 1) / PAGE_SIZE;
-        //let new_page = (new_brk + PAGE_SIZE - 1) / PAGE_SIZE;
-        let cur_page = task_inner.max_data_addr / PAGE_SIZE;
-        let mut new_page = num;
-        if need_align {
-            new_page += 1;
-        }
-        let page_count = new_page - cur_page;
-        //println!("{} - {}", new_page, cur_page);
-        let mut all_vpn = Vec::<VirtPage>::new();
-        let mut all_ppn = Vec::<PhysPage>::new();
-        if page_count > 0 {
-            // 申请等量的物理页帧
-            /*let frames = frame_alloc_more(page_count);
-            if frames.is_none() {
-                return -1; // 物理内存不足
-            }
-            let frames = frames.unwrap();*/
-
-            // 在 memory_set 中映射新增的虚拟页号到物理页帧,如(31,32)->(31,30.9->31) 实际申请一页
-            //let _start_va: VirtAddr = (cur_brk).into();
-            //let _end_va: VirtAddr = (new_brk - PAGE_SIZE -1).into();
-            
-            for i in 0..page_count {
-                let vpn = VirtPage::from(cur_page + i);
-                //let ppn = frames[i].ppn;
-                let mp = MapPermission::R | MapPermission::W | MapPermission::U;
-                let ppn = task_inner.memory_set.map_page(vpn, mp, MappingSize::Page4KB);
-                all_vpn.push(vpn);
-                all_ppn.push(ppn);
-                //println!("vpn:{} ppn:{}",vpn,ppn);
-                /*task_inner.memory_set.map_page(
-                    vpn,
-                    ppn,
-                    MapPermission::R | MapPermission::W | MapPermission::U,
-                    MappingSize::Page4KB,
-                );*/
-            }
-        }
+        let cur_addr = VirtAddr::new(task_inner.max_data_addr).floor();
+        let new_addr = VirtAddr::new(new_brk).ceil();
+        
+        let page_count = (new_addr.addr() - cur_addr.addr()) / PAGE_SIZE;
+        let alloc_start_addr = task_inner.max_data_addr;
+        task_inner.memory_set.push_into_heaparea(
+            MapArea::new(
+                VirtAddr::new(alloc_start_addr), //向下
+                VirtAddr::new(new_brk), //向上
+                MapType::Framed,
+                MapPermission::R|MapPermission::U|MapPermission::W|MapPermission::X
+            ),
+            None
+        );
         task_inner.max_data_addr += PAGE_SIZE*page_count;
         //println!("max_data_addr = {}", task_inner.max_data_addr);
         task_inner.heap_top = new_brk;
-        /*for (vpn, ppn) in all_vpn.iter().zip(all_ppn.iter()) {
-            println!("VPN: {:?}, PPN: {:?}", vpn, ppn);
-        }*/
+        
         0
     }
     else if new_brk == cur_brk {
diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs
index 44737bb..afa020e 100644
--- a/os/src/task/mod.rs
+++ b/os/src/task/mod.rs
@@ -30,7 +30,7 @@ use arch::KContext;
 use arch::TrapFrameArgs;
 use lazy_static::*;
 pub use manager::{fetch_task, TaskManager,wakeup_task};
-pub use task::{TaskControlBlock, TaskStatus, Tms, Utsname};
+pub use task::{TaskControlBlock, TaskStatus, Tms, Utsname, MapFdControl};
 use vfs_defs::OpenFlags;
 pub use manager::add_task;
 pub use pid::{pid_alloc,  PidAllocator, PidHandle};
diff --git a/os/src/task/task.rs b/os/src/task/task.rs
index bc6a56e..791de5c 100644
--- a/os/src/task/task.rs
+++ b/os/src/task/task.rs
@@ -1,7 +1,7 @@
 //!Implementation of [`TaskControlBlock`]
 use super::current_task;
 use super::{pid_alloc, PidHandle};
-use crate::config::{KERNEL_STACK_SIZE, USER_STACK_SIZE};
+use crate::config::{KERNEL_STACK_SIZE, USER_MMAP_TOP, USER_STACK_SIZE};
 use crate::fs::{Stdin, Stdout};
 use crate::mm::{translated_refmut, MapArea, MapPermission, MapType, MemorySet};
 use arch::addr::VirtAddr;
@@ -127,7 +127,61 @@ pub struct TaskControlBlock {
     // mutable
     inner: Mutex<TaskControlBlockInner>,
 }
-
+#[derive(Clone)]
+pub struct MapAreaControl {
+    pub mmap_top: usize,
+    pub mapfd: Vec<MapFdControl>,
+    mapfreeblock: Vec<MapFreeControl>,
+}
+impl MapAreaControl {
+    pub fn new() -> Self {
+        Self { 
+            mmap_top: USER_MMAP_TOP, 
+            mapfd: Vec::new(), 
+            mapfreeblock: Vec::new() 
+        }
+    }
+    // 找到第一个合适的块
+    pub fn find_block(&mut self, num: usize) -> usize {
+        for (i, block) in self.mapfreeblock.iter_mut().enumerate() {
+            if block.num >= num {
+                block.num -= num;
+                if block.num == 0 {
+                    // 移除当前块并返回起始dizhi
+                    return self.mapfreeblock.swap_remove(i).start_va;
+                } else {
+                    return block.start_va;
+                }
+            }
+        }
+        0
+    }
+    // 找fd
+    pub fn find_fd(&mut self, start: usize, len: &mut usize) -> isize {
+        for (i, block) in self.mapfd.iter_mut().enumerate() {
+            if start == block.start_va {
+                *len = self.mapfd[i].len;
+                return self.mapfd.swap_remove(i).fd as isize;
+            }
+        }
+        return -1;
+    }
+}
+///
+#[derive(Clone)]
+pub struct MapFdControl {
+    ///
+    pub fd: usize,
+    ///
+    pub len: usize,
+    ///
+    pub start_va: usize,
+}
+#[derive(Clone)]
+pub struct MapFreeControl {
+    pub start_va: usize,
+    pub num: usize,
+}
 pub struct TaskControlBlockInner {
     pub trap_cx: TrapFrame,
     #[allow(unused)]
@@ -146,6 +200,8 @@ pub struct TaskControlBlockInner {
     pub stack_bottom: usize,
     pub max_data_addr: usize,
     pub tms: Tms,
+    pub mapareacontrol: MapAreaControl,
+    //pub mmap_top: usize,
 }
 fn task_entry() {
     let task = current_task()
@@ -232,6 +288,8 @@ impl TaskControlBlock {
                     stack_bottom: user_sp - USER_STACK_SIZE,
                     max_data_addr: heap_top,
                     tms: Tms::new(),
+                    mapareacontrol: MapAreaControl::new(),
+                    //mmap_top: USER_MMAP_TOP,
                     }
                 ),
         };
@@ -259,6 +317,7 @@ impl TaskControlBlock {
         self.inner_exclusive_access().stack_bottom =user_sp - USER_STACK_SIZE;
         self.inner_exclusive_access().max_data_addr = heap_top;
         self.inner_exclusive_access().tms= Tms::new();
+        self.inner_exclusive_access().mapareacontrol = MapAreaControl::new();
         memory_set.activate();
         // push arguments on user stack
         user_sp -= (args.len() + 1) * core::mem::size_of::<usize>();
@@ -340,6 +399,8 @@ impl TaskControlBlock {
                     stack_bottom: parent_inner.stack_bottom,
                     max_data_addr: parent_inner.max_data_addr,
                     tms: Tms::from_other_task(&parent_inner.tms),
+                    mapareacontrol: parent_inner.mapareacontrol.clone(),
+                    //mmap_top: parent_inner.mmap_top,
                 })
             ,
         });
diff --git a/user/src/bin/brktest.rs b/user/src/bin/brktest.rs
index 9db0639..bea8da9 100644
--- a/user/src/bin/brktest.rs
+++ b/user/src/bin/brktest.rs
@@ -33,7 +33,7 @@ const PAGE_SIZE: isize= 4096;
 #[no_mangle]
 pub fn main() -> i32 {
     let init_brk = brk(0);
-    let size: isize = 6000;
+    let size: isize = 2000;
     for i in 1..5 {
         
         println!("第{}轮扩充({}):", i, size/PAGE_SIZE + 1);
diff --git a/user/src/bin/mmap.rs b/user/src/bin/mmap.rs
new file mode 100644
index 0000000..1434c51
--- /dev/null
+++ b/user/src/bin/mmap.rs
@@ -0,0 +1,12 @@
+#![no_std]
+#![no_main]
+
+#[macro_use]
+extern crate user_lib;
+//use user_lib::{exit, fork, wait, waitpid, yield_};
+
+#[no_mangle]
+pub fn main() -> i32 {
+
+    0
+}
\ No newline at end of file
diff --git a/user/src/bin/rwo.rs b/user/src/bin/rwo.rs
new file mode 100644
index 0000000..79dde37
--- /dev/null
+++ b/user/src/bin/rwo.rs
@@ -0,0 +1,58 @@
+#![no_std]
+#![no_main]
+
+#[macro_use]
+extern crate user_lib;
+extern  crate alloc;
+use alloc::vec;
+use core::{convert::TryInto, str};
+use user_lib::{open,write,read,OpenFlags,close};
+
+
+#[no_mangle]
+pub fn main() -> i32 {// 测试 open, write, read 功能
+    const FILE_NAME: &str = "./testfile.txt";
+    const CONTENT: &str = "Hello, Rust userland!";
+ 
+    // 打开或创建文件(O_CREATE | O_WRONLY | O_TRUNC)
+    let flags = OpenFlags::CREATE | OpenFlags::WRONLY | OpenFlags::TRUNC;
+    let fd = open(FILE_NAME, flags);
+    if fd < 0 {
+        println!("Failed to open file: {}", fd);
+        return -1;
+    }
+    println!("File opened successfully, fd: {}", fd);
+ 
+    // 写入文件
+    let content_bytes = CONTENT.as_bytes();
+    let bytes_written = write(fd.try_into().unwrap(), content_bytes);
+    if bytes_written < 0 {
+        println!("Failed to write to file: {}", bytes_written);
+        close(fd.try_into().unwrap());
+        return -1;
+    }
+    println!("Written {} bytes to file", bytes_written);
+ 
+    // 读取文件内容
+    let mut buffer = vec![0u8; 128]; // 假设缓冲区足够大
+    let bytes_read = read(fd.try_into().unwrap(), &mut buffer);
+    if bytes_read < 0 {
+        println!("Failed to read from file: {}", bytes_read);
+        close(fd.try_into().unwrap());
+        return -1;
+    }
+    println!("Read {} bytes from file", bytes_read);
+ 
+    // 将读取的内容转换为字符串并打印
+    let content = str::from_utf8(&buffer[..bytes_read as usize]).unwrap_or("<invalid UTF-8>");
+    println!("File content: {}", content);
+ 
+    // 关闭文件
+    if close(fd.try_into().unwrap()) < 0 {
+        println!("Failed to close file");
+        return -1;
+    }
+    println!("File closed successfully after reading");
+ 
+    0 // 正常退出
+}
\ No newline at end of file
diff --git a/vfs-defs/src/file.rs b/vfs-defs/src/file.rs
index aac9504..8187700 100644
--- a/vfs-defs/src/file.rs
+++ b/vfs-defs/src/file.rs
@@ -83,7 +83,7 @@ pub trait File: Send + Sync{
         self.get_inner().dentry.clone()
     }
     /// Read file to `buf`
-    fn read(&self,   buf: &mut [u8]) -> usize{
+    fn read(&self, buf: &mut [u8]) -> usize{
         let mut offset = self.get_offset();
         let read_size = self.read_at(*offset, buf);
         *offset += read_size;
-- 
GitLab