Browse Source

fix(mm): 修复fat文件系统的PageCache同步问题 (#1005)

---------

Co-authored-by: longjin <[email protected]>
MemoryShore 2 months ago
parent
commit
e92424df8d

+ 0 - 1
kernel/Cargo.toml

@@ -63,7 +63,6 @@ paste = "=1.0.14"
 slabmalloc = { path = "crates/rust-slabmalloc" }
 log = "0.4.21"
 kprobe = { path = "crates/kprobe" }
-xarray = "0.1.0"
 lru = "0.12.3"
 
 rbpf = { path = "crates/rbpf" }

+ 2 - 6
kernel/src/driver/net/dma.rs

@@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags;
 use crate::arch::MMArch;
 
 use crate::mm::kernel_mapper::KernelMapper;
-use crate::mm::page::{page_manager_lock_irqsave, EntryFlags};
+use crate::mm::page::EntryFlags;
 use crate::mm::{
     allocator::page_frame::{
         allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
@@ -61,11 +61,7 @@ pub unsafe fn dma_dealloc(paddr: usize, vaddr: NonNull<u8>, pages: usize) -> i32
     flusher.flush();
 
     unsafe {
-        deallocate_page_frames(
-            PhysPageFrame::new(PhysAddr::new(paddr)),
-            page_count,
-            &mut page_manager_lock_irqsave(),
-        );
+        deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
     }
     return 0;
 }

+ 2 - 6
kernel/src/driver/virtio/virtio_impl.rs

@@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags;
 use crate::arch::MMArch;
 
 use crate::mm::kernel_mapper::KernelMapper;
-use crate::mm::page::{page_manager_lock_irqsave, EntryFlags};
+use crate::mm::page::EntryFlags;
 use crate::mm::{
     allocator::page_frame::{
         allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
@@ -72,11 +72,7 @@ unsafe impl Hal for HalImpl {
         flusher.flush();
 
         unsafe {
-            deallocate_page_frames(
-                PhysPageFrame::new(PhysAddr::new(paddr)),
-                page_count,
-                &mut page_manager_lock_irqsave(),
-            );
+            deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
         }
         return 0;
     }

+ 98 - 29
kernel/src/filesystem/fat/fs.rs

@@ -14,7 +14,7 @@ use alloc::{
 
 use crate::driver::base::block::gendisk::GenDisk;
 use crate::driver::base::device::device_number::DeviceNumber;
-use crate::filesystem::vfs::file::PageCache;
+use crate::filesystem::page_cache::PageCache;
 use crate::filesystem::vfs::utils::DName;
 use crate::filesystem::vfs::{Magic, SpecialNodeData, SuperBlock};
 use crate::ipc::pipe::LockedPipeInode;
@@ -129,9 +129,8 @@ pub struct FATInode {
 }
 
 impl FATInode {
-    /// @brief 更新当前inode的元数据
-    pub fn update_metadata(&mut self) {
-        // todo: 更新文件的访问时间等信息
+    /// 将inode的元数据与磁盘同步
+    pub fn synchronize_metadata(&mut self) {
         match &self.inode_type {
             FATDirEntry::File(f) | FATDirEntry::VolId(f) => {
                 self.metadata.size = f.size() as i64;
@@ -146,6 +145,19 @@ impl FATInode {
         };
     }
 
+    /// 更新inode的元数据
+    pub fn update_metadata(&mut self, size: Option<i64>) {
+        if let Some(new_size) = size {
+            self.metadata.size = new_size;
+        }
+        self.update_time();
+    }
+
+    /// 更新访问时间
+    pub fn update_time(&mut self) {
+        // log::warn!("update_time has not yet been implemented");
+    }
+
     fn find(&mut self, name: &str) -> Result<Arc<LockedFATInode>, SystemError> {
         match &self.inode_type {
             FATDirEntry::Dir(d) => {
@@ -234,7 +246,7 @@ impl LockedFATInode {
 
         inode.0.lock().self_ref = Arc::downgrade(&inode);
 
-        inode.0.lock().update_metadata();
+        inode.0.lock().synchronize_metadata();
 
         return inode;
     }
@@ -1386,24 +1398,14 @@ impl FATFsInfo {
 }
 
 impl IndexNode for LockedFATInode {
-    fn read_at(
-        &self,
-        offset: usize,
-        len: usize,
-        buf: &mut [u8],
-        _data: SpinLockGuard<FilePrivateData>,
-    ) -> Result<usize, SystemError> {
-        let mut guard: SpinLockGuard<FATInode> = self.0.lock();
+    fn read_sync(&self, offset: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let guard: SpinLockGuard<FATInode> = self.0.lock();
         match &guard.inode_type {
             FATDirEntry::File(f) | FATDirEntry::VolId(f) => {
-                let r = f.read(
-                    &guard.fs.upgrade().unwrap(),
-                    &mut buf[0..len],
-                    offset as u64,
-                );
-                guard.update_metadata();
+                let r = f.read(&guard.fs.upgrade().unwrap(), buf, offset as u64);
                 return r;
             }
+
             FATDirEntry::Dir(_) => {
                 return Err(SystemError::EISDIR);
             }
@@ -1414,25 +1416,20 @@ impl IndexNode for LockedFATInode {
         }
     }
 
-    fn write_at(
-        &self,
-        offset: usize,
-        len: usize,
-        buf: &[u8],
-        _data: SpinLockGuard<FilePrivateData>,
-    ) -> Result<usize, SystemError> {
+    fn write_sync(&self, offset: usize, buf: &[u8]) -> Result<usize, SystemError> {
         let mut guard: SpinLockGuard<FATInode> = self.0.lock();
         let fs: &Arc<FATFileSystem> = &guard.fs.upgrade().unwrap();
 
         match &mut guard.inode_type {
             FATDirEntry::File(f) | FATDirEntry::VolId(f) => {
-                let r = f.write(fs, &buf[0..len], offset as u64);
-                guard.update_metadata();
+                let r = f.write(fs, buf, offset as u64);
                 return r;
             }
+
             FATDirEntry::Dir(_) => {
                 return Err(SystemError::EISDIR);
             }
+
             FATDirEntry::UnInit => {
                 error!("FATFS: param: Inode_type uninitialized.");
                 return Err(SystemError::EROFS);
@@ -1440,6 +1437,74 @@ impl IndexNode for LockedFATInode {
         }
     }
 
+    fn read_at(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &mut [u8],
+        data: SpinLockGuard<FilePrivateData>,
+    ) -> Result<usize, SystemError> {
+        let len = core::cmp::min(len, buf.len());
+        let buf = &mut buf[0..len];
+
+        let page_cache = self.0.lock().page_cache.clone();
+        if let Some(page_cache) = page_cache {
+            let r = page_cache.lock_irqsave().read(offset, &mut buf[0..len]);
+            // self.0.lock_irqsave().update_metadata();
+            return r;
+        } else {
+            return self.read_direct(offset, len, buf, data);
+        }
+    }
+
+    fn write_at(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &[u8],
+        data: SpinLockGuard<FilePrivateData>,
+    ) -> Result<usize, SystemError> {
+        let len = core::cmp::min(len, buf.len());
+        let buf = &buf[0..len];
+
+        let page_cache = self.0.lock().page_cache.clone();
+        if let Some(page_cache) = page_cache {
+            let write_len = page_cache.lock_irqsave().write(offset, buf)?;
+            let mut guard = self.0.lock();
+            let old_size = guard.metadata.size;
+            guard.update_metadata(Some(core::cmp::max(old_size, (offset + write_len) as i64)));
+            return Ok(write_len);
+        } else {
+            return self.write_direct(offset, len, buf, data);
+        }
+    }
+
+    fn read_direct(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &mut [u8],
+        _data: SpinLockGuard<FilePrivateData>,
+    ) -> Result<usize, SystemError> {
+        let len = core::cmp::min(len, buf.len());
+        let r = self.read_sync(offset, &mut buf[0..len]);
+        // self.0.lock_irqsave().update_metadata();
+        return r;
+    }
+
+    fn write_direct(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &[u8],
+        _data: SpinLockGuard<FilePrivateData>,
+    ) -> Result<usize, SystemError> {
+        let len = core::cmp::min(len, buf.len());
+        let r = self.write_sync(offset, &buf[0..len]);
+        // self.0.lock_irqsave().update_metadata();
+        return r;
+    }
+
     fn create(
         &self,
         name: &str,
@@ -1496,6 +1561,10 @@ impl IndexNode for LockedFATInode {
         Ok(())
     }
     fn resize(&self, len: usize) -> Result<(), SystemError> {
+        if let Some(page_cache) = self.page_cache() {
+            return page_cache.lock_irqsave().resize(len);
+        }
+
         let mut guard: SpinLockGuard<FATInode> = self.0.lock();
         let fs: &Arc<FATFileSystem> = &guard.fs.upgrade().unwrap();
         let old_size = guard.metadata.size as usize;
@@ -1527,7 +1596,7 @@ impl IndexNode for LockedFATInode {
                         file.truncate(fs, len as u64)?;
                     }
                 }
-                guard.update_metadata();
+                guard.synchronize_metadata();
                 return Ok(());
             }
             FATDirEntry::Dir(_) => return Err(SystemError::ENOSYS),

+ 1 - 0
kernel/src/filesystem/mod.rs

@@ -5,6 +5,7 @@ pub mod fat;
 pub mod kernfs;
 pub mod mbr;
 pub mod overlayfs;
+pub mod page_cache;
 pub mod procfs;
 pub mod ramfs;
 pub mod sysfs;

+ 346 - 0
kernel/src/filesystem/page_cache.rs

@@ -0,0 +1,346 @@
+use core::cmp::min;
+
+use alloc::{
+    sync::{Arc, Weak},
+    vec::Vec,
+};
+use hashbrown::HashMap;
+use system_error::SystemError;
+
+use super::vfs::IndexNode;
+use crate::libs::spinlock::SpinLockGuard;
+use crate::mm::page::FileMapInfo;
+use crate::{arch::mm::LockedFrameAllocator, libs::lazy_init::Lazy};
+use crate::{
+    arch::MMArch,
+    libs::spinlock::SpinLock,
+    mm::{
+        page::{page_manager_lock_irqsave, page_reclaimer_lock_irqsave, Page, PageFlags},
+        MemoryManagementArch,
+    },
+};
+use crate::{libs::align::page_align_up, mm::page::PageType};
+
+/// 页面缓存
+#[derive(Debug)]
+pub struct PageCache {
+    inner: SpinLock<InnerPageCache>,
+    inode: Lazy<Weak<dyn IndexNode>>,
+}
+
+#[derive(Debug)]
+pub struct InnerPageCache {
+    pages: HashMap<usize, Arc<Page>>,
+    page_cache_ref: Weak<PageCache>,
+}
+
+impl InnerPageCache {
+    pub fn new(page_cache_ref: Weak<PageCache>) -> InnerPageCache {
+        Self {
+            pages: HashMap::new(),
+            page_cache_ref,
+        }
+    }
+
+    pub fn add_page(&mut self, offset: usize, page: &Arc<Page>) {
+        self.pages.insert(offset, page.clone());
+    }
+
+    pub fn get_page(&self, offset: usize) -> Option<Arc<Page>> {
+        self.pages.get(&offset).cloned()
+    }
+
+    pub fn remove_page(&mut self, offset: usize) -> Option<Arc<Page>> {
+        self.pages.remove(&offset)
+    }
+
+    fn create_pages(&mut self, start_page_index: usize, buf: &[u8]) -> Result<(), SystemError> {
+        assert!(buf.len() % MMArch::PAGE_SIZE == 0);
+
+        let page_num = buf.len() / MMArch::PAGE_SIZE;
+
+        let len = buf.len();
+        if len == 0 {
+            return Ok(());
+        }
+
+        let mut page_manager_guard = page_manager_lock_irqsave();
+
+        for i in 0..page_num {
+            let buf_offset = i * MMArch::PAGE_SIZE;
+            let page_index = start_page_index + i;
+
+            let page = page_manager_guard.create_one_page(
+                PageType::File(FileMapInfo {
+                    page_cache: self
+                        .page_cache_ref
+                        .upgrade()
+                        .expect("failed to get self_arc of pagecache"),
+                    index: page_index,
+                }),
+                PageFlags::PG_LRU,
+                &mut LockedFrameAllocator,
+            )?;
+
+            let mut page_guard = page.write_irqsave();
+            unsafe {
+                page_guard.copy_from_slice(&buf[buf_offset..buf_offset + MMArch::PAGE_SIZE]);
+            }
+
+            self.add_page(page_index, &page);
+        }
+
+        Ok(())
+    }
+
+    /// 从PageCache中读取数据。
+    ///
+    /// ## 参数
+    ///
+    /// - `offset` 偏移量
+    /// - `buf` 缓冲区
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok(usize)` 成功读取的长度
+    /// - `Err(SystemError)` 失败返回错误码
+    pub fn read(&mut self, offset: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let inode = self
+            .page_cache_ref
+            .upgrade()
+            .unwrap()
+            .inode
+            .upgrade()
+            .unwrap();
+        let file_size = inode.metadata().unwrap().size;
+
+        let len = if offset < file_size as usize {
+            core::cmp::min(file_size as usize, offset + buf.len()) - offset
+        } else {
+            0
+        };
+
+        if len == 0 {
+            return Ok(0);
+        }
+
+        let mut not_exist = Vec::new();
+
+        let start_page_index = offset >> MMArch::PAGE_SHIFT;
+        let page_num = (page_align_up(offset + len) >> MMArch::PAGE_SHIFT) - start_page_index;
+
+        let mut buf_offset = 0;
+        let mut ret = 0;
+        for i in 0..page_num {
+            let page_index = start_page_index + i;
+
+            // 第一个页可能需要计算页内偏移
+            let page_offset = if i == 0 {
+                offset % MMArch::PAGE_SIZE
+            } else {
+                0
+            };
+
+            // 第一个页和最后一个页可能不满
+            let sub_len = if i == 0 {
+                min(len, MMArch::PAGE_SIZE - page_offset)
+            } else if i == page_num - 1 {
+                (offset + len - 1) % MMArch::PAGE_SIZE + 1
+            } else {
+                MMArch::PAGE_SIZE
+            };
+
+            if let Some(page) = self.get_page(page_index) {
+                let sub_buf = &mut buf[buf_offset..(buf_offset + sub_len)];
+                unsafe {
+                    sub_buf.copy_from_slice(
+                        &page.read_irqsave().as_slice()[page_offset..page_offset + sub_len],
+                    );
+                }
+                ret += sub_len;
+            } else if let Some((index, count)) = not_exist.last_mut() {
+                if *index + *count == page_index {
+                    *count += 1;
+                } else {
+                    not_exist.push((page_index, 1));
+                }
+            } else {
+                not_exist.push((page_index, 1));
+            }
+
+            buf_offset += sub_len;
+        }
+
+        for (page_index, count) in not_exist {
+            // TODO 这里使用buffer避免多次读取磁盘,将来引入异步IO直接写入页面,减少内存开销和拷贝
+            let mut page_buf = vec![0u8; MMArch::PAGE_SIZE * count];
+            inode.read_sync(page_index * MMArch::PAGE_SIZE, page_buf.as_mut())?;
+
+            self.create_pages(page_index, page_buf.as_mut())?;
+
+            // 实际要拷贝的内容在文件中的偏移量
+            let copy_offset = core::cmp::max(page_index * MMArch::PAGE_SIZE, offset);
+            // 实际要拷贝的内容的长度
+            let copy_len = core::cmp::min((page_index + count) * MMArch::PAGE_SIZE, offset + len)
+                - copy_offset;
+
+            let page_buf_offset = if page_index * MMArch::PAGE_SIZE < copy_offset {
+                copy_offset - page_index * MMArch::PAGE_SIZE
+            } else {
+                0
+            };
+
+            let buf_offset = copy_offset.saturating_sub(offset);
+
+            buf[buf_offset..buf_offset + copy_len]
+                .copy_from_slice(&page_buf[page_buf_offset..page_buf_offset + copy_len]);
+
+            ret += copy_len;
+
+            // log::debug!("page_offset:{page_offset}, count:{count}");
+            // log::debug!("copy_offset:{copy_offset}, copy_len:{copy_len}");
+            // log::debug!("buf_offset:{buf_offset}, page_buf_offset:{page_buf_offset}");
+        }
+
+        Ok(ret)
+    }
+
+    /// 向PageCache中写入数据。
+    ///
+    /// ## 参数
+    ///
+    /// - `offset` 偏移量
+    /// - `buf` 缓冲区
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok(usize)` 成功读取的长度
+    /// - `Err(SystemError)` 失败返回错误码
+    pub fn write(&mut self, offset: usize, buf: &[u8]) -> Result<usize, SystemError> {
+        let len = buf.len();
+        if len == 0 {
+            return Ok(0);
+        }
+
+        // log::debug!("offset:{offset}, len:{len}");
+
+        let start_page_index = offset >> MMArch::PAGE_SHIFT;
+        let page_num = (page_align_up(offset + len) >> MMArch::PAGE_SHIFT) - start_page_index;
+
+        let mut buf_offset = 0;
+        let mut ret = 0;
+
+        for i in 0..page_num {
+            let page_index = start_page_index + i;
+
+            // 第一个页可能需要计算页内偏移
+            let page_offset = if i == 0 {
+                offset % MMArch::PAGE_SIZE
+            } else {
+                0
+            };
+
+            // 第一个页和最后一个页可能不满
+            let sub_len = if i == 0 {
+                min(len, MMArch::PAGE_SIZE - page_offset)
+            } else if i == page_num - 1 {
+                (offset + len - 1) % MMArch::PAGE_SIZE + 1
+            } else {
+                MMArch::PAGE_SIZE
+            };
+
+            let mut page = self.get_page(page_index);
+
+            if page.is_none() {
+                let page_buf = vec![0u8; MMArch::PAGE_SIZE];
+                self.create_pages(page_index, &page_buf)?;
+                page = self.get_page(page_index);
+            }
+
+            if let Some(page) = page {
+                let sub_buf = &buf[buf_offset..(buf_offset + sub_len)];
+                let mut page_guard = page.write_irqsave();
+                unsafe {
+                    page_guard.as_slice_mut()[page_offset..page_offset + sub_len]
+                        .copy_from_slice(sub_buf);
+                }
+                page_guard.add_flags(PageFlags::PG_DIRTY);
+
+                ret += sub_len;
+
+                // log::debug!(
+                //     "page_offset:{page_offset}, buf_offset:{buf_offset}, sub_len:{sub_len}"
+                // );
+            } else {
+                return Err(SystemError::EIO);
+            };
+
+            buf_offset += sub_len;
+        }
+        Ok(ret)
+    }
+
+    pub fn resize(&mut self, len: usize) -> Result<(), SystemError> {
+        let page_num = page_align_up(len) / MMArch::PAGE_SIZE;
+
+        let mut reclaimer = page_reclaimer_lock_irqsave();
+        for (_i, page) in self.pages.drain_filter(|index, _page| *index >= page_num) {
+            let _ = reclaimer.remove_page(&page.phys_address());
+        }
+
+        if page_num > 0 {
+            let last_page_index = page_num - 1;
+            let last_len = len - last_page_index * MMArch::PAGE_SIZE;
+            if let Some(page) = self.get_page(last_page_index) {
+                unsafe {
+                    page.write_irqsave().truncate(last_len);
+                };
+            } else {
+                return Err(SystemError::EIO);
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl Drop for InnerPageCache {
+    fn drop(&mut self) {
+        log::debug!("page cache drop");
+        let mut page_manager = page_manager_lock_irqsave();
+        for page in self.pages.values() {
+            page_manager.remove_page(&page.phys_address());
+        }
+    }
+}
+
+impl PageCache {
+    pub fn new(inode: Option<Weak<dyn IndexNode>>) -> Arc<PageCache> {
+        Arc::new_cyclic(|weak| Self {
+            inner: SpinLock::new(InnerPageCache::new(weak.clone())),
+            inode: {
+                let v: Lazy<Weak<dyn IndexNode>> = Lazy::new();
+                if let Some(inode) = inode {
+                    v.init(inode);
+                }
+                v
+            },
+        })
+    }
+
+    pub fn inode(&self) -> Option<Weak<dyn IndexNode>> {
+        self.inode.try_get().cloned()
+    }
+
+    pub fn set_inode(&self, inode: Weak<dyn IndexNode>) -> Result<(), SystemError> {
+        if self.inode.initialized() {
+            return Err(SystemError::EINVAL);
+        }
+        self.inode.init(inode);
+        Ok(())
+    }
+
+    pub fn lock_irqsave(&self) -> SpinLockGuard<InnerPageCache> {
+        self.inner.lock_irqsave()
+    }
+}

+ 23 - 86
kernel/src/filesystem/vfs/file.rs

@@ -5,16 +5,13 @@ use alloc::{
     sync::{Arc, Weak},
     vec::Vec,
 };
-use kdepends::xarray::XArray;
 use log::error;
 use system_error::SystemError;
 
 use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
 use crate::filesystem::eventfd::EventFdInode;
-use crate::libs::lazy_init::Lazy;
 use crate::perf::PerfEventInode;
 use crate::{
-    arch::MMArch,
     driver::{
         base::{block::SeekFrom, device::DevicePrivateData},
         tty::tty_device::TtyFilePrivateData,
@@ -22,7 +19,6 @@ use crate::{
     filesystem::procfs::ProcfsFilePrivateData,
     ipc::pipe::{LockedPipeInode, PipeFsPrivateData},
     libs::{rwlock::RwLock, spinlock::SpinLock},
-    mm::{page::Page, MemoryManagementArch},
     net::{
         event_poll::{EPollItem, EPollPrivateData, EventPoll},
         socket::SocketInode,
@@ -124,75 +120,6 @@ impl FileMode {
     }
 }
 
-/// 页面缓存
-pub struct PageCache {
-    xarray: SpinLock<XArray<Arc<Page>>>,
-    inode: Lazy<Weak<dyn IndexNode>>,
-}
-
-impl core::fmt::Debug for PageCache {
-    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
-        f.debug_struct("PageCache")
-            .field(
-                "xarray",
-                &self
-                    .xarray
-                    .lock()
-                    .range(0..((MMArch::PAGE_ADDRESS_SIZE >> MMArch::PAGE_SHIFT) as u64))
-                    .map(|(_, r)| (*r).clone())
-                    .collect::<Vec<Arc<Page>>>(),
-            )
-            .finish()
-    }
-}
-
-impl PageCache {
-    pub fn new(inode: Option<Weak<dyn IndexNode>>) -> Arc<PageCache> {
-        let page_cache = Self {
-            xarray: SpinLock::new(XArray::new()),
-            inode: {
-                let v: Lazy<Weak<dyn IndexNode>> = Lazy::new();
-                if let Some(inode) = inode {
-                    v.init(inode);
-                }
-                v
-            },
-        };
-        Arc::new(page_cache)
-    }
-
-    pub fn inode(&self) -> Option<Weak<dyn IndexNode>> {
-        self.inode.try_get().cloned()
-    }
-
-    pub fn add_page(&self, offset: usize, page: &Arc<Page>) {
-        let mut guard = self.xarray.lock();
-        let mut cursor = guard.cursor_mut(offset as u64);
-        cursor.store(page.clone());
-    }
-
-    pub fn get_page(&self, offset: usize) -> Option<Arc<Page>> {
-        let mut guard = self.xarray.lock();
-        let mut cursor = guard.cursor_mut(offset as u64);
-        let page = cursor.load().map(|r| (*r).clone());
-        page
-    }
-
-    pub fn remove_page(&self, offset: usize) {
-        let mut guard = self.xarray.lock();
-        let mut cursor = guard.cursor_mut(offset as u64);
-        cursor.remove();
-    }
-
-    pub fn set_inode(&self, inode: Weak<dyn IndexNode>) -> Result<(), SystemError> {
-        if self.inode.initialized() {
-            return Err(SystemError::EINVAL);
-        }
-        self.inode.init(inode);
-        Ok(())
-    }
-}
-
 /// @brief 抽象文件结构体
 #[derive(Debug)]
 pub struct File {
@@ -238,13 +165,16 @@ impl File {
         return Ok(f);
     }
 
-    /// @brief 从文件中读取指定的字节数到buffer中
+    /// ## 从文件中读取指定的字节数到buffer中
     ///
-    /// @param len 要读取的字节数
-    /// @param buf 目标buffer
+    /// ### 参数
+    /// - `len`: 要读取的字节数
+    /// - `buf`: 缓冲区
+    /// - `read_direct`: 忽略缓存,直接读取磁盘
     ///
-    /// @return Ok(usize) 成功读取的字节数
-    /// @return Err(SystemError) 错误码
+    /// ### 返回值
+    /// - `Ok(usize)`: 成功读取的字节数
+    /// - `Err(SystemError)`: 错误码
     pub fn read(&self, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
         self.do_read(
             self.offset.load(core::sync::atomic::Ordering::SeqCst),
@@ -254,13 +184,16 @@ impl File {
         )
     }
 
-    /// @brief 从buffer向文件写入指定的字节数的数据
+    /// ## 从buffer向文件写入指定的字节数的数据
     ///
-    /// @param len 要写入的字节数
-    /// @param buf 源数据buffer
+    /// ### 参数
+    /// - `offset`: 文件偏移量
+    /// - `len`: 要写入的字节数
+    /// - `buf`: 写入缓冲区
     ///
-    /// @return Ok(usize) 成功写入的字节数
-    /// @return Err(SystemError) 错误码
+    /// ### 返回值
+    /// - `Ok(usize)`: 成功写入的字节数
+    /// - `Err(SystemError)`: 错误码
     pub fn write(&self, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
         self.do_write(
             self.offset.load(core::sync::atomic::Ordering::SeqCst),
@@ -309,9 +242,13 @@ impl File {
             return Err(SystemError::ENOBUFS);
         }
 
-        let len = self
-            .inode
-            .read_at(offset, len, buf, self.private_data.lock())?;
+        let len = if self.mode().contains(FileMode::O_DIRECT) {
+            self.inode
+                .read_direct(offset, len, buf, self.private_data.lock())
+        } else {
+            self.inode
+                .read_at(offset, len, buf, self.private_data.lock())
+        }?;
 
         if update_offset {
             self.offset

+ 58 - 6
kernel/src/filesystem/vfs/mod.rs

@@ -24,14 +24,11 @@ use crate::{
     time::PosixTimeSpec,
 };
 
-use self::{
-    core::generate_inode_id,
-    file::{FileMode, PageCache},
-    syscall::ModeType,
-    utils::DName,
-};
+use self::{core::generate_inode_id, file::FileMode, syscall::ModeType, utils::DName};
 pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS};
 
+use super::page_cache::PageCache;
+
 /// vfs容许的最大的路径名称长度
 pub const MAX_PATHLEN: usize = 1024;
 
@@ -128,6 +125,15 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync {
     fn mmap(&self, _start: usize, _len: usize, _offset: usize) -> Result<(), SystemError> {
         return Err(SystemError::ENOSYS);
     }
+
+    fn read_sync(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize, SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
+    fn write_sync(&self, _offset: usize, _buf: &[u8]) -> Result<usize, SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
     /// @brief 打开文件
     ///
     /// @return 成功:Ok()
@@ -184,6 +190,52 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync {
         _data: SpinLockGuard<FilePrivateData>,
     ) -> Result<usize, SystemError>;
 
+    /// # 在inode的指定偏移量开始,读取指定大小的数据,忽略PageCache
+    ///
+    /// ## 参数
+    ///
+    /// - `offset`: 起始位置在Inode中的偏移量
+    /// - `len`: 要读取的字节数
+    /// - `buf`: 缓冲区
+    /// - `data`: 各文件系统系统所需私有信息
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok(usize)``: Ok(读取的字节数)
+    /// - `Err(SystemError)``: Err(Posix错误码)
+    fn read_direct(
+        &self,
+        _offset: usize,
+        _len: usize,
+        _buf: &mut [u8],
+        _data: SpinLockGuard<FilePrivateData>,
+    ) -> Result<usize, SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
+    /// # 在inode的指定偏移量开始,写入指定大小的数据,忽略PageCache
+    ///
+    /// ## 参数
+    ///
+    /// - `offset`: 起始位置在Inode中的偏移量
+    /// - `len`: 要读取的字节数
+    /// - `buf`: 缓冲区
+    /// - `data`: 各文件系统系统所需私有信息
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok(usize)``: Ok(读取的字节数)
+    /// - `Err(SystemError)``: Err(Posix错误码)
+    fn write_direct(
+        &self,
+        _offset: usize,
+        _len: usize,
+        _buf: &[u8],
+        _data: SpinLockGuard<FilePrivateData>,
+    ) -> Result<usize, SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
     /// @brief 获取当前inode的状态。
     ///
     /// @return PollStatus结构体

+ 23 - 5
kernel/src/filesystem/vfs/mount.rs

@@ -14,7 +14,7 @@ use system_error::SystemError;
 
 use crate::{
     driver::base::device::device_number::DeviceNumber,
-    filesystem::vfs::ROOT_INODE,
+    filesystem::{page_cache::PageCache, vfs::ROOT_INODE},
     libs::{
         casting::DowncastArc,
         rwlock::RwLock,
@@ -24,10 +24,8 @@ use crate::{
 };
 
 use super::{
-    file::{FileMode, PageCache},
-    syscall::ModeType,
-    utils::DName,
-    FilePrivateData, FileSystem, FileType, IndexNode, InodeId, Magic, SuperBlock,
+    file::FileMode, syscall::ModeType, utils::DName, FilePrivateData, FileSystem, FileType,
+    IndexNode, InodeId, Magic, SuperBlock,
 };
 
 const MOUNTFS_BLOCK_SIZE: u64 = 512;
@@ -296,6 +294,26 @@ impl IndexNode for MountFSInode {
         return self.inner_inode.write_at(offset, len, buf, data);
     }
 
+    fn read_direct(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &mut [u8],
+        data: SpinLockGuard<FilePrivateData>,
+    ) -> Result<usize, SystemError> {
+        self.inner_inode.read_direct(offset, len, buf, data)
+    }
+
+    fn write_direct(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &[u8],
+        data: SpinLockGuard<FilePrivateData>,
+    ) -> Result<usize, SystemError> {
+        self.inner_inode.write_direct(offset, len, buf, data)
+    }
+
     #[inline]
     fn fs(&self) -> Arc<dyn FileSystem> {
         return self.mount_fs.clone();

+ 27 - 35
kernel/src/ipc/shm.rs

@@ -7,16 +7,15 @@ use crate::{
     },
     mm::{
         allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame},
-        page::{page_manager_lock_irqsave, Page},
+        page::{page_manager_lock_irqsave, PageFlags, PageType},
         PhysAddr,
     },
     process::{Pid, ProcessManager},
     syscall::user_access::{UserBufferReader, UserBufferWriter},
     time::PosixTimeSpec,
 };
-use alloc::{sync::Arc, vec::Vec};
 use core::sync::atomic::{compiler_fence, Ordering};
-use hashbrown::{HashMap, HashSet};
+use hashbrown::HashMap;
 use ida::IdAllocator;
 use log::info;
 use num::ToPrimitive;
@@ -159,21 +158,16 @@ impl ShmManager {
 
         // 分配共享内存页面
         let page_count = PageFrameCount::from_bytes(page_align_up(size)).unwrap();
-        let phys_page =
-            unsafe { LockedFrameAllocator.allocate(page_count) }.ok_or(SystemError::EINVAL)?;
         // 创建共享内存page,并添加到PAGE_MANAGER中
         let mut page_manager_guard = page_manager_lock_irqsave();
-        let mut cur_phys = PhysPageFrame::new(phys_page.0);
-        for _ in 0..page_count.data() {
-            let page = Arc::new(Page::new(true, cur_phys.phys_address()));
-            page.write_irqsave().set_shm_id(shm_id);
-            let paddr = cur_phys.phys_address();
-            page_manager_guard.insert(paddr, &page);
-            cur_phys = cur_phys.next();
-        }
+        let (paddr, _page) = page_manager_guard.create_pages(
+            PageType::Shm(shm_id),
+            PageFlags::PG_UNEVICTABLE,
+            &mut LockedFrameAllocator,
+            page_count,
+        )?;
 
         // 创建共享内存信息结构体
-        let paddr = phys_page.0;
         let kern_ipc_perm = KernIpcPerm {
             id: shm_id,
             key,
@@ -323,9 +317,10 @@ impl ShmManager {
         let mut page_manager_guard = page_manager_lock_irqsave();
         if map_count > 0 {
             // 设置共享内存物理页当映射计数等于0时可被回收
+            // TODO 后续需要加入到lru中
             for _ in 0..count.data() {
                 let page = page_manager_guard.get_unwrap(&cur_phys.phys_address());
-                page.write_irqsave().set_dealloc_when_zero(true);
+                page.write_irqsave().remove_flags(PageFlags::PG_UNEVICTABLE);
 
                 cur_phys = cur_phys.next();
             }
@@ -375,6 +370,8 @@ pub struct KernelShm {
     shm_start_paddr: PhysAddr,
     /// 共享内存大小(bytes),注意是用户指定的大小(未经过页面对齐)
     shm_size: usize,
+    /// 映射计数
+    map_count: usize,
     /// 最后一次连接的时间
     shm_atim: PosixTimeSpec,
     /// 最后一次断开连接的时间
@@ -394,6 +391,7 @@ impl KernelShm {
             kern_ipc_perm,
             shm_start_paddr,
             shm_size,
+            map_count: 0,
             shm_atim: PosixTimeSpec::new(0, 0),
             shm_dtim: PosixTimeSpec::new(0, 0),
             shm_ctim: PosixTimeSpec::now(),
@@ -436,26 +434,7 @@ impl KernelShm {
 
     /// 共享内存段的映射计数(有多少个不同的VMA映射)
     pub fn map_count(&self) -> usize {
-        let mut page_manager_guard = page_manager_lock_irqsave();
-        let mut id_set: HashSet<usize> = HashSet::new();
-        let mut cur_phys = PhysPageFrame::new(self.shm_start_paddr);
-        let page_count = PageFrameCount::from_bytes(page_align_up(self.shm_size)).unwrap();
-
-        for _ in 0..page_count.data() {
-            let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap();
-            id_set.extend(
-                page.read_irqsave()
-                    .anon_vma()
-                    .iter()
-                    .map(|vma| vma.id())
-                    .collect::<Vec<_>>(),
-            );
-
-            cur_phys = cur_phys.next();
-        }
-
-        // 由于LockedVMA的id是独一无二的,因此有多少个不同的id,就代表着有多少个不同的VMA映射到共享内存段
-        return id_set.len();
+        self.map_count
     }
 
     pub fn copy_from(&mut self, shm_id_ds: PosixShmIdDs) {
@@ -474,6 +453,19 @@ impl KernelShm {
 
         self.update_ctim();
     }
+
+    pub fn mode(&self) -> &ShmFlags {
+        &self.kern_ipc_perm.mode
+    }
+
+    pub fn increase_count(&mut self) {
+        self.map_count += 1;
+    }
+
+    pub fn decrease_count(&mut self) {
+        assert!(self.map_count > 0, "map_count is zero");
+        self.map_count -= 1;
+    }
 }
 
 /// 共享内存权限信息

+ 4 - 25
kernel/src/ipc/syscall.rs

@@ -16,8 +16,7 @@ use crate::{
         FilePrivateData,
     },
     ipc::shm::{shm_manager_lock, IPC_PRIVATE},
-    libs::align::page_align_up,
-    libs::spinlock::SpinLock,
+    libs::{align::page_align_up, spinlock::SpinLock},
     mm::{
         allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame},
         page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll},
@@ -405,6 +404,9 @@ impl Syscall {
         // 更新最后一次连接时间
         kernel_shm.update_atim();
 
+        // 映射计数增加
+        kernel_shm.increase_count();
+
         Ok(r)
     }
 
@@ -433,29 +435,6 @@ impl Syscall {
             return Err(SystemError::EINVAL);
         }
 
-        // 获取映射的物理地址
-        let paddr = address_write_guard
-            .user_mapper
-            .utable
-            .translate(vaddr)
-            .ok_or(SystemError::EINVAL)?
-            .0;
-
-        // 如果物理页的shm_id为None,代表不是共享页
-        let mut page_manager_guard = page_manager_lock_irqsave();
-        let page = page_manager_guard.get(&paddr).ok_or(SystemError::EINVAL)?;
-        let shm_id = page.read_irqsave().shm_id().ok_or(SystemError::EINVAL)?;
-        drop(page_manager_guard);
-
-        // 获取对应共享页管理信息
-        let mut shm_manager_guard = shm_manager_lock();
-        let kernel_shm = shm_manager_guard
-            .get_mut(&shm_id)
-            .ok_or(SystemError::EINVAL)?;
-        // 更新最后一次断开连接时间
-        kernel_shm.update_dtim();
-        drop(shm_manager_guard);
-
         // 取消映射
         let flusher: PageFlushAll<MMArch> = PageFlushAll::new();
         vma.unmap(&mut address_write_guard.user_mapper.utable, flusher);

+ 4 - 26
kernel/src/mm/allocator/page_frame.rs

@@ -5,8 +5,6 @@ use core::{
 
 use crate::{
     arch::{mm::LockedFrameAllocator, MMArch},
-    ipc::shm::shm_manager_lock,
-    libs::spinlock::SpinLockGuard,
     mm::{MemoryManagementArch, PhysAddr, VirtAddr},
 };
 
@@ -173,6 +171,8 @@ impl Iterator for VirtPageFrameIter {
 pub struct PageFrameCount(usize);
 
 impl PageFrameCount {
+    pub const ONE: PageFrameCount = PageFrameCount(1);
+
     // @brief 初始化PageFrameCount
     pub const fn new(count: usize) -> Self {
         return Self(count);
@@ -355,30 +355,8 @@ pub unsafe fn allocate_page_frames(count: PageFrameCount) -> Option<(PhysAddr, P
 ///
 /// @param frame 要释放的第一个页帧
 /// @param count 要释放的页帧数量 (必须是2的n次幂)
-pub unsafe fn deallocate_page_frames(
-    frame: PhysPageFrame,
-    count: PageFrameCount,
-    page_manager_guard: &mut SpinLockGuard<'_, crate::mm::page::PageManager>,
-) {
+pub unsafe fn deallocate_page_frames(frame: PhysPageFrame, count: PageFrameCount) {
     unsafe {
         LockedFrameAllocator.free(frame.phys_address(), count);
-    }
-
-    let mut frame = frame;
-    for _ in 0..count.data() {
-        let paddr = frame.phys_address();
-        let page = page_manager_guard.get(&paddr);
-
-        if let Some(page) = page {
-            // 如果page是共享页,将其共享页信息从SHM_MANAGER中删去
-            let page_guard = page.read_irqsave();
-            if page_guard.shared() {
-                shm_manager_lock().free_id(&page_guard.shm_id().unwrap());
-            }
-        }
-
-        // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去
-        page_manager_guard.remove_page(&paddr);
-        frame = frame.next();
-    }
+    };
 }

+ 23 - 38
kernel/src/mm/fault.rs

@@ -22,7 +22,7 @@ use crate::mm::MemoryManagementArch;
 
 use super::{
     allocator::page_frame::FrameAllocator,
-    page::{page_reclaimer_lock_irqsave, Page, PageFlags},
+    page::{FileMapInfo, Page, PageFlags, PageType},
 };
 
 bitflags! {
@@ -55,7 +55,7 @@ pub struct PageFaultMessage<'a> {
     flags: FaultFlags,
     /// 页表映射器
     mapper: &'a mut PageMapper,
-    /// 缺页的文件页在文件中的偏移
+    /// 缺页的文件页在文件中的偏移页号
     file_pgoff: Option<usize>,
     /// 缺页对应PageCache中的文件页
     page: Option<Arc<Page>>,
@@ -308,32 +308,14 @@ impl PageFaultHandler {
         let cache_page = pfm.page.clone().unwrap();
         let mapper = &mut pfm.mapper;
 
-        let cow_page_phys = mapper.allocator_mut().allocate_one();
-        if cow_page_phys.is_none() {
+        let mut page_manager_guard = page_manager_lock_irqsave();
+        if let Ok(page) =
+            page_manager_guard.copy_page(&cache_page.phys_address(), mapper.allocator_mut())
+        {
+            pfm.cow_page = Some(page.clone());
+        } else {
             return VmFaultReason::VM_FAULT_OOM;
         }
-        let cow_page_phys = cow_page_phys.unwrap();
-
-        let cow_page = Arc::new(Page::new(false, cow_page_phys));
-        pfm.cow_page = Some(cow_page.clone());
-
-        //复制PageCache内容到新的页内
-        let new_frame = MMArch::phys_2_virt(cow_page_phys).unwrap();
-        (new_frame.data() as *mut u8).copy_from_nonoverlapping(
-            MMArch::phys_2_virt(cache_page.read_irqsave().phys_address())
-                .unwrap()
-                .data() as *mut u8,
-            MMArch::PAGE_SIZE,
-        );
-
-        let mut page_manager_guard = page_manager_lock_irqsave();
-
-        // 新页加入页管理器中
-        page_manager_guard.insert(cow_page_phys, &cow_page);
-        cow_page.write_irqsave().set_page_cache_index(
-            cache_page.read_irqsave().page_cache(),
-            cache_page.read_irqsave().index(),
-        );
 
         ret = ret.union(Self::finish_fault(pfm));
 
@@ -608,10 +590,10 @@ impl PageFaultHandler {
                 << MMArch::PAGE_SHIFT);
 
         for pgoff in start_pgoff..=end_pgoff {
-            if let Some(page) = page_cache.get_page(pgoff) {
+            if let Some(page) = page_cache.lock_irqsave().get_page(pgoff) {
                 let page_guard = page.read_irqsave();
                 if page_guard.flags().contains(PageFlags::PG_UPTODATE) {
-                    let phys = page_guard.phys_address();
+                    let phys = page.phys_address();
 
                     let address =
                         VirtAddr::new(addr.data() + ((pgoff - start_pgoff) << MMArch::PAGE_SHIFT));
@@ -642,7 +624,7 @@ impl PageFaultHandler {
         let mapper = &mut pfm.mapper;
         let mut ret = VmFaultReason::empty();
 
-        if let Some(page) = page_cache.get_page(file_pgoff) {
+        if let Some(page) = page_cache.lock_irqsave().get_page(file_pgoff) {
             // TODO 异步从磁盘中预读页面进PageCache
 
             // 直接将PageCache中的页面作为要映射的页面
@@ -669,16 +651,19 @@ impl PageFaultHandler {
             )
             .expect("failed to read file to create pagecache page");
 
-            let page = Arc::new(Page::new(true, new_cache_page));
+            let page = page_manager_lock_irqsave()
+                .create_one_page(
+                    PageType::File(FileMapInfo {
+                        page_cache: page_cache.clone(),
+                        index: file_pgoff,
+                    }),
+                    PageFlags::PG_LRU,
+                    allocator,
+                )
+                .expect("failed to create page");
             pfm.page = Some(page.clone());
 
-            page.write_irqsave().add_flags(PageFlags::PG_LRU);
-            page_manager_lock_irqsave().insert(new_cache_page, &page);
-            page_reclaimer_lock_irqsave().insert_page(new_cache_page, &page);
-            page_cache.add_page(file_pgoff, &page);
-
-            page.write_irqsave()
-                .set_page_cache_index(Some(page_cache), Some(file_pgoff));
+            page_cache.lock_irqsave().add_page(file_pgoff, &page);
         }
         ret
     }
@@ -710,7 +695,7 @@ impl PageFaultHandler {
             cache_page.expect("no cache_page in PageFaultMessage")
         };
 
-        let page_phys = page_to_map.read_irqsave().phys_address();
+        let page_phys = page_to_map.phys_address();
 
         mapper.map_phys(address, page_phys, vma_guard.flags());
         page_to_map.write_irqsave().insert_vma(pfm.vma());

+ 342 - 144
kernel/src/mm/page.rs

@@ -1,4 +1,4 @@
-use alloc::string::ToString;
+use alloc::{string::ToString, vec::Vec};
 use core::{
     fmt::{self, Debug, Error, Formatter},
     marker::PhantomData,
@@ -17,7 +17,7 @@ use lru::LruCache;
 use crate::{
     arch::{interrupt::ipi::send_ipi, mm::LockedFrameAllocator, MMArch},
     exception::ipi::{IpiKind, IpiTarget},
-    filesystem::vfs::{file::PageCache, FilePrivateData},
+    filesystem::{page_cache::PageCache, vfs::FilePrivateData},
     init::initcall::INITCALL_CORE,
     ipc::shm::ShmId,
     libs::{
@@ -29,7 +29,9 @@ use crate::{
 };
 
 use super::{
-    allocator::page_frame::{FrameAllocator, PageFrameCount},
+    allocator::page_frame::{
+        deallocate_page_frames, FrameAllocator, PageFrameCount, PhysPageFrame,
+    },
     syscall::ProtFlags,
     ucontext::LockedVMA,
     MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
@@ -74,6 +76,7 @@ impl PageManager {
         }
     }
 
+    #[allow(dead_code)]
     pub fn contains(&self, paddr: &PhysAddr) -> bool {
         self.phys2page.contains_key(paddr)
     }
@@ -91,13 +94,121 @@ impl PageManager {
             .clone()
     }
 
-    pub fn insert(&mut self, paddr: PhysAddr, page: &Arc<Page>) {
-        self.phys2page.insert(paddr, page.clone());
+    fn insert(&mut self, page: &Arc<Page>) -> Result<Arc<Page>, SystemError> {
+        let phys = page.phys_address();
+        if !self.phys2page.contains_key(&phys) {
+            self.phys2page.insert(phys, page.clone());
+            Ok(page.clone())
+        } else {
+            log::error!("phys page: {phys:?} already exists.");
+            Err(SystemError::EINVAL)
+        }
     }
 
     pub fn remove_page(&mut self, paddr: &PhysAddr) {
         self.phys2page.remove(paddr);
     }
+
+    /// # 创建一个新页面并加入管理器
+    ///
+    /// ## 参数
+    ///
+    /// - `shared`: 是否共享
+    /// - `page_type`: 页面类型
+    /// - `flags`: 页面标志
+    /// - `allocator`: 物理页帧分配器
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok(Arc<Page>)`: 新页面
+    /// - `Err(SystemError)`: 错误码
+    pub fn create_one_page(
+        &mut self,
+        page_type: PageType,
+        flags: PageFlags,
+        allocator: &mut dyn FrameAllocator,
+    ) -> Result<Arc<Page>, SystemError> {
+        self.create_pages(page_type, flags, allocator, PageFrameCount::ONE)?
+            .1
+            .first()
+            .ok_or(SystemError::ENOMEM)
+            .cloned()
+    }
+
+    /// # 创建新页面并加入管理器
+    ///
+    /// ## 参数
+    ///
+    /// - `shared`: 是否共享
+    /// - `page_type`: 页面类型
+    /// - `flags`: 页面标志
+    /// - `allocator`: 物理页帧分配器
+    /// - `count`: 页面数量
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok((PhysAddr, Vec<Arc<Page>>))`: 页面起始物理地址,新页面集合
+    /// - `Err(SystemError)`: 错误码
+    pub fn create_pages(
+        &mut self,
+        page_type: PageType,
+        flags: PageFlags,
+        allocator: &mut dyn FrameAllocator,
+        count: PageFrameCount,
+    ) -> Result<(PhysAddr, Vec<Arc<Page>>), SystemError> {
+        compiler_fence(Ordering::SeqCst);
+        let (start_paddr, count) = unsafe { allocator.allocate(count).ok_or(SystemError::ENOMEM)? };
+        compiler_fence(Ordering::SeqCst);
+
+        unsafe {
+            let vaddr = MMArch::phys_2_virt(start_paddr).unwrap();
+            MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE * count.data());
+        }
+
+        let mut cur_phys = PhysPageFrame::new(start_paddr);
+        let mut ret: Vec<Arc<Page>> = Vec::new();
+        for _ in 0..count.data() {
+            let page = Page::new(cur_phys.phys_address(), page_type.clone(), flags);
+            if let Err(e) = self.insert(&page) {
+                for insert_page in ret {
+                    self.remove_page(&insert_page.read_irqsave().phys_addr);
+                }
+                return Err(e);
+            }
+            ret.push(page);
+            cur_phys = cur_phys.next();
+        }
+        Ok((start_paddr, ret))
+    }
+
+    /// # 拷贝管理器中原有页面并加入管理器,同时拷贝原页面内容
+    ///
+    /// ## 参数
+    ///
+    /// - `old_phys`: 原页面的物理地址
+    /// - `allocator`: 物理页帧分配器
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok(Arc<Page>)`: 新页面
+    /// - `Err(SystemError)`: 错误码
+    pub fn copy_page(
+        &mut self,
+        old_phys: &PhysAddr,
+        allocator: &mut dyn FrameAllocator,
+    ) -> Result<Arc<Page>, SystemError> {
+        let old_page = self.get(old_phys).ok_or(SystemError::EINVAL)?;
+        let paddr = unsafe { allocator.allocate_one().ok_or(SystemError::ENOMEM)? };
+
+        assert!(!self.contains(&paddr), "phys page: {paddr:?} already exist");
+
+        let page = Page::copy(old_page.read_irqsave(), paddr)
+            .inspect_err(|_| unsafe { allocator.free_one(paddr) })?;
+
+        self.insert(&page)?;
+
+        Ok(page)
+    }
 }
 
 pub static mut PAGE_RECLAIMER: Option<SpinLock<PageReclaimer>> = None;
@@ -150,7 +261,7 @@ fn page_reclaim_thread() -> i32 {
             page_reclaimer_lock_irqsave().flush_dirty_pages();
             // 休眠5秒
             // log::info!("sleep");
-            let _ = nanosleep(PosixTimeSpec::new(5, 0));
+            let _ = nanosleep(PosixTimeSpec::new(0, 500_000_000));
         }
     }
 }
@@ -180,28 +291,31 @@ impl PageReclaimer {
         self.lru.put(paddr, page.clone());
     }
 
+    pub fn remove_page(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
+        self.lru.pop(paddr)
+    }
+
     /// lru链表缩减
     /// ## 参数
     ///
     /// - `count`: 需要缩减的页面数量
     pub fn shrink_list(&mut self, count: PageFrameCount) {
         for _ in 0..count.data() {
-            let (paddr, page) = self.lru.pop_lru().expect("pagecache is empty");
-            let page_cache = page.read_irqsave().page_cache().unwrap();
-            for vma in page.read_irqsave().anon_vma() {
-                let address_space = vma.lock_irqsave().address_space().unwrap();
-                let address_space = address_space.upgrade().unwrap();
-                let mut guard = address_space.write();
-                let mapper = &mut guard.user_mapper.utable;
-                let virt = vma.lock_irqsave().page_address(&page).unwrap();
-                unsafe {
-                    mapper.unmap(virt, false).unwrap().flush();
+            let (_, page) = self.lru.pop_lru().expect("pagecache is empty");
+            let mut guard = page.write_irqsave();
+            if let PageType::File(info) = guard.page_type().clone() {
+                let page_cache = &info.page_cache;
+                let page_index = info.index;
+                let paddr = guard.phys_address();
+                if guard.flags().contains(PageFlags::PG_DIRTY) {
+                    // 先回写脏页
+                    Self::page_writeback(&mut guard, true);
                 }
-            }
-            page_cache.remove_page(page.read_irqsave().index().unwrap());
-            page_manager_lock_irqsave().remove_page(&paddr);
-            if page.read_irqsave().flags.contains(PageFlags::PG_DIRTY) {
-                Self::page_writeback(&page, true);
+
+                // 删除页面
+                page_cache.lock_irqsave().remove_page(page_index);
+                page_manager_lock_irqsave().remove_page(&paddr);
+                self.remove_page(&paddr);
             }
         }
     }
@@ -215,24 +329,33 @@ impl PageReclaimer {
     /// 脏页回写函数
     /// ## 参数
     ///
-    /// - `page`: 需要回写的脏页
+    /// - `guard`: 需要回写的脏页
     /// - `unmap`: 是否取消映射
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    pub fn page_writeback(page: &Arc<Page>, unmap: bool) {
-        if !unmap {
-            page.write_irqsave().remove_flags(PageFlags::PG_DIRTY);
-        }
+    pub fn page_writeback(guard: &mut RwLockWriteGuard<InnerPage>, unmap: bool) {
+        // log::debug!("page writeback: {:?}", guard.phys_addr);
+
+        let (page_cache, page_index) = match guard.page_type() {
+            PageType::File(info) => (info.page_cache.clone(), info.index),
+            _ => {
+                log::warn!("try to writeback a non-file page");
+                return;
+            }
+        };
+        let paddr = guard.phys_address();
+        let inode = page_cache.inode().clone().unwrap().upgrade().unwrap();
 
-        for vma in page.read_irqsave().anon_vma() {
+        for vma in guard.vma_set() {
             let address_space = vma.lock_irqsave().address_space().unwrap();
             let address_space = address_space.upgrade().unwrap();
             let mut guard = address_space.write();
             let mapper = &mut guard.user_mapper.utable;
-            let virt = vma.lock_irqsave().page_address(page).unwrap();
+            let virt = vma.lock_irqsave().page_address(page_index).unwrap();
             if unmap {
                 unsafe {
+                    // 取消页表映射
                     mapper.unmap(virt, false).unwrap().flush();
                 }
             } else {
@@ -245,40 +368,44 @@ impl PageReclaimer {
                 };
             }
         }
-        let inode = page
-            .read_irqsave()
-            .page_cache
-            .clone()
-            .unwrap()
-            .inode()
-            .clone()
-            .unwrap()
-            .upgrade()
-            .unwrap();
+
+        let len = if let Ok(metadata) = inode.metadata() {
+            let size = metadata.size as usize;
+            if size < page_index * MMArch::PAGE_SIZE {
+                0
+            } else {
+                size - page_index * MMArch::PAGE_SIZE
+            }
+        } else {
+            MMArch::PAGE_SIZE
+        };
+
         inode
-            .write_at(
-                page.read_irqsave().index().unwrap(),
-                MMArch::PAGE_SIZE,
+            .write_direct(
+                page_index * MMArch::PAGE_SIZE,
+                len,
                 unsafe {
                     core::slice::from_raw_parts(
-                        MMArch::phys_2_virt(page.read_irqsave().phys_addr)
-                            .unwrap()
-                            .data() as *mut u8,
-                        MMArch::PAGE_SIZE,
+                        MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8,
+                        len,
                     )
                 },
                 SpinLock::new(FilePrivateData::Unused).lock(),
             )
             .unwrap();
+
+        // 清除标记
+        guard.remove_flags(PageFlags::PG_DIRTY);
     }
 
     /// lru脏页刷新
-    pub fn flush_dirty_pages(&self) {
+    pub fn flush_dirty_pages(&mut self) {
         // log::info!("flush_dirty_pages");
         let iter = self.lru.iter();
-        for (_, page) in iter {
-            if page.read_irqsave().flags().contains(PageFlags::PG_DIRTY) {
-                Self::page_writeback(page, false);
+        for (_paddr, page) in iter {
+            let mut guard = page.write_irqsave();
+            if guard.flags().contains(PageFlags::PG_DIRTY) {
+                Self::page_writeback(&mut guard, false);
             }
         }
     }
@@ -302,20 +429,76 @@ bitflags! {
         const PG_PRIVATE = 1 << 15;
         const PG_RECLAIM = 1 << 18;
         const PG_SWAPBACKED = 1 << 19;
+        const PG_UNEVICTABLE = 1 << 20;
     }
 }
 
 #[derive(Debug)]
 pub struct Page {
     inner: RwLock<InnerPage>,
+    /// 页面所在物理地址
+    phys_addr: PhysAddr,
 }
 
 impl Page {
-    pub fn new(shared: bool, phys_addr: PhysAddr) -> Self {
-        let inner = InnerPage::new(shared, phys_addr);
-        Self {
+    /// # 创建新页面
+    ///
+    /// ## 参数
+    ///
+    /// - `shared`: 是否共享
+    /// - `phys_addr`: 物理地址
+    /// - `page_type`: 页面类型
+    /// - `flags`: 页面标志
+    ///
+    /// ## 返回值
+    ///
+    /// - `Arc<Page>`: 新页面
+    fn new(phys_addr: PhysAddr, page_type: PageType, flags: PageFlags) -> Arc<Page> {
+        let inner = InnerPage::new(phys_addr, page_type, flags);
+        let page = Arc::new(Self {
             inner: RwLock::new(inner),
+            phys_addr,
+        });
+        if page.read_irqsave().flags == PageFlags::PG_LRU {
+            page_reclaimer_lock_irqsave().insert_page(phys_addr, &page);
+        };
+        page
+    }
+
+    /// # 拷贝页面及内容
+    ///
+    /// ## 参数
+    ///
+    /// - `old_guard`: 源页面的读守卫
+    /// - `new_phys`: 新页面的物理地址
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok(Arc<Page>)`: 新页面
+    /// - `Err(SystemError)`: 错误码
+    fn copy(
+        old_guard: RwLockReadGuard<InnerPage>,
+        new_phys: PhysAddr,
+    ) -> Result<Arc<Page>, SystemError> {
+        let page_type = old_guard.page_type().clone();
+        let flags = *old_guard.flags();
+        let inner = InnerPage::new(new_phys, page_type, flags);
+        unsafe {
+            let old_vaddr =
+                MMArch::phys_2_virt(old_guard.phys_address()).ok_or(SystemError::EFAULT)?;
+            let new_vaddr = MMArch::phys_2_virt(new_phys).ok_or(SystemError::EFAULT)?;
+            (new_vaddr.data() as *mut u8)
+                .copy_from_nonoverlapping(old_vaddr.data() as *mut u8, MMArch::PAGE_SIZE);
         }
+        Ok(Arc::new(Self {
+            inner: RwLock::new(inner),
+            phys_addr: new_phys,
+        }))
+    }
+
+    #[inline(always)]
+    pub fn phys_address(&self) -> PhysAddr {
+        self.phys_addr
     }
 
     pub fn read_irqsave(&self) -> RwLockReadGuard<InnerPage> {
@@ -330,107 +513,68 @@ impl Page {
 #[derive(Debug)]
 /// 物理页面信息
 pub struct InnerPage {
-    /// 映射计数
-    map_count: usize,
-    /// 是否为共享页
-    shared: bool,
-    /// 映射计数为0时,是否可回收
-    free_when_zero: bool,
-    /// 共享页id(如果是共享页)
-    shm_id: Option<ShmId>,
     /// 映射到当前page的VMA
-    anon_vma: HashSet<Arc<LockedVMA>>,
+    vma_set: HashSet<Arc<LockedVMA>>,
     /// 标志
     flags: PageFlags,
-    /// 页所在的物理页帧号
+    /// 页面所在物理地址
     phys_addr: PhysAddr,
-    /// 在pagecache中的偏移
-    index: Option<usize>,
-    page_cache: Option<Arc<PageCache>>,
+    /// 页面类型
+    page_type: PageType,
 }
 
 impl InnerPage {
-    pub fn new(shared: bool, phys_addr: PhysAddr) -> Self {
-        let dealloc_when_zero = !shared;
+    pub fn new(phys_addr: PhysAddr, page_type: PageType, flags: PageFlags) -> Self {
         Self {
-            map_count: 0,
-            shared,
-            free_when_zero: dealloc_when_zero,
-            shm_id: None,
-            anon_vma: HashSet::new(),
-            flags: PageFlags::empty(),
+            vma_set: HashSet::new(),
+            flags,
             phys_addr,
-            index: None,
-            page_cache: None,
+            page_type,
         }
     }
 
     /// 将vma加入anon_vma
     pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
-        self.anon_vma.insert(vma);
-        self.map_count += 1;
+        self.vma_set.insert(vma);
     }
 
     /// 将vma从anon_vma中删去
     pub fn remove_vma(&mut self, vma: &LockedVMA) {
-        self.anon_vma.remove(vma);
-        self.map_count -= 1;
+        self.vma_set.remove(vma);
     }
 
     /// 判断当前物理页是否能被回
     pub fn can_deallocate(&self) -> bool {
-        self.map_count == 0 && self.free_when_zero
+        self.map_count() == 0 && !self.flags.contains(PageFlags::PG_UNEVICTABLE)
     }
 
     pub fn shared(&self) -> bool {
-        self.shared
-    }
-
-    pub fn shm_id(&self) -> Option<ShmId> {
-        self.shm_id
-    }
-
-    pub fn index(&self) -> Option<usize> {
-        self.index
+        self.map_count() > 1
     }
 
     pub fn page_cache(&self) -> Option<Arc<PageCache>> {
-        self.page_cache.clone()
-    }
-
-    pub fn set_page_cache(&mut self, page_cache: Option<Arc<PageCache>>) {
-        self.page_cache = page_cache;
-    }
-
-    pub fn set_index(&mut self, index: Option<usize>) {
-        self.index = index;
-    }
-
-    pub fn set_page_cache_index(
-        &mut self,
-        page_cache: Option<Arc<PageCache>>,
-        index: Option<usize>,
-    ) {
-        self.page_cache = page_cache;
-        self.index = index;
+        match &self.page_type {
+            PageType::File(info) => Some(info.page_cache.clone()),
+            _ => None,
+        }
     }
 
-    pub fn set_shm_id(&mut self, shm_id: ShmId) {
-        self.shm_id = Some(shm_id);
+    pub fn page_type(&self) -> &PageType {
+        &self.page_type
     }
 
-    pub fn set_dealloc_when_zero(&mut self, dealloc_when_zero: bool) {
-        self.free_when_zero = dealloc_when_zero;
+    pub fn set_page_type(&mut self, page_type: PageType) {
+        self.page_type = page_type;
     }
 
     #[inline(always)]
-    pub fn anon_vma(&self) -> &HashSet<Arc<LockedVMA>> {
-        &self.anon_vma
+    pub fn vma_set(&self) -> &HashSet<Arc<LockedVMA>> {
+        &self.vma_set
     }
 
     #[inline(always)]
     pub fn map_count(&self) -> usize {
-        self.map_count
+        self.vma_set.len()
     }
 
     #[inline(always)]
@@ -454,9 +598,83 @@ impl InnerPage {
     }
 
     #[inline(always)]
-    pub fn phys_address(&self) -> PhysAddr {
+    fn phys_address(&self) -> PhysAddr {
         self.phys_addr
     }
+
+    pub unsafe fn as_slice(&self) -> &[u8] {
+        core::slice::from_raw_parts(
+            MMArch::phys_2_virt(self.phys_addr).unwrap().data() as *const u8,
+            MMArch::PAGE_SIZE,
+        )
+    }
+
+    pub unsafe fn as_slice_mut(&mut self) -> &mut [u8] {
+        core::slice::from_raw_parts_mut(
+            MMArch::phys_2_virt(self.phys_addr).unwrap().data() as *mut u8,
+            MMArch::PAGE_SIZE,
+        )
+    }
+
+    pub unsafe fn copy_from_slice(&mut self, slice: &[u8]) {
+        assert_eq!(
+            slice.len(),
+            MMArch::PAGE_SIZE,
+            "length of slice not match PAGE_SIZE"
+        );
+        core::slice::from_raw_parts_mut(
+            MMArch::phys_2_virt(self.phys_addr).unwrap().data() as *mut u8,
+            MMArch::PAGE_SIZE,
+        )
+        .copy_from_slice(slice);
+    }
+
+    pub unsafe fn truncate(&mut self, len: usize) {
+        if len > MMArch::PAGE_SIZE {
+            return;
+        }
+
+        let vaddr = unsafe { MMArch::phys_2_virt(self.phys_addr).unwrap() };
+
+        unsafe {
+            core::slice::from_raw_parts_mut(
+                (vaddr.data() + len) as *mut u8,
+                MMArch::PAGE_SIZE - len,
+            )
+            .fill(0)
+        };
+    }
+}
+
+impl Drop for InnerPage {
+    fn drop(&mut self) {
+        assert!(
+            self.map_count() == 0,
+            "page drop when map count is non-zero"
+        );
+
+        unsafe {
+            deallocate_page_frames(PhysPageFrame::new(self.phys_addr), PageFrameCount::new(1))
+        };
+    }
+}
+
+/// 页面类型,包含额外的页面信息
+#[derive(Debug, Clone)]
+pub enum PageType {
+    /// 普通页面,不含额外信息
+    Normal,
+    /// 文件映射页,含文件映射相关信息
+    File(FileMapInfo),
+    /// 共享内存页,记录ShmId
+    Shm(ShmId),
+}
+
+#[derive(Debug, Clone)]
+pub struct FileMapInfo {
+    pub page_cache: Arc<PageCache>,
+    /// 在pagecache中的偏移
+    pub index: usize,
 }
 
 #[derive(Debug)]
@@ -634,23 +852,7 @@ impl<Arch: MemoryManagementArch> PageTable<Arch> {
                             let phys = allocator.allocate_one()?;
                             let mut page_manager_guard = page_manager_lock_irqsave();
                             let old_phys = entry.address().unwrap();
-                            let old_page = page_manager_guard.get_unwrap(&old_phys);
-                            let new_page =
-                                Arc::new(Page::new(old_page.read_irqsave().shared(), phys));
-                            if let Some(ref page_cache) = old_page.read_irqsave().page_cache() {
-                                new_page.write_irqsave().set_page_cache_index(
-                                    Some(page_cache.clone()),
-                                    old_page.read_irqsave().index(),
-                                );
-                            }
-
-                            page_manager_guard.insert(phys, &new_page);
-                            let old_phys = entry.address().unwrap();
-                            let frame = MMArch::phys_2_virt(phys).unwrap().data() as *mut u8;
-                            frame.copy_from_nonoverlapping(
-                                MMArch::phys_2_virt(old_phys).unwrap().data() as *mut u8,
-                                MMArch::PAGE_SIZE,
-                            );
+                            page_manager_guard.copy_page(&old_phys, allocator).ok()?;
                             new_table.set_entry(i, PageEntry::new(phys, entry.flags()));
                         }
                     }
@@ -1180,21 +1382,17 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
         virt: VirtAddr,
         flags: EntryFlags<Arch>,
     ) -> Option<PageFlush<Arch>> {
-        compiler_fence(Ordering::SeqCst);
-        let phys: PhysAddr = self.frame_allocator.allocate_one()?;
-        compiler_fence(Ordering::SeqCst);
-
-        unsafe {
-            let vaddr = MMArch::phys_2_virt(phys).unwrap();
-            MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE);
-        }
-
         let mut page_manager_guard: SpinLockGuard<'static, PageManager> =
             page_manager_lock_irqsave();
-        if !page_manager_guard.contains(&phys) {
-            page_manager_guard.insert(phys, &Arc::new(Page::new(false, phys)))
-        }
+        let page = page_manager_guard
+            .create_one_page(
+                PageType::Normal,
+                PageFlags::empty(),
+                &mut self.frame_allocator,
+            )
+            .ok()?;
         drop(page_manager_guard);
+        let phys = page.phys_address();
         return self.map_phys(virt, phys, flags);
     }
 

+ 34 - 18
kernel/src/mm/ucontext.rs

@@ -21,6 +21,7 @@ use crate::{
     arch::{mm::PageMapper, CurrentIrqArch, MMArch},
     exception::InterruptArch,
     filesystem::vfs::file::File,
+    ipc::shm::{shm_manager_lock, ShmFlags},
     libs::{
         align::page_align_up,
         rwlock::RwLock,
@@ -35,7 +36,7 @@ use super::{
     allocator::page_frame::{
         deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter,
     },
-    page::{EntryFlags, Flusher, InactiveFlusher, Page, PageFlushAll},
+    page::{EntryFlags, Flusher, InactiveFlusher, PageFlushAll, PageType},
     syscall::{MadvFlags, MapFlags, MremapFlags, ProtFlags},
     MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion, VmFlags,
 };
@@ -841,7 +842,6 @@ impl Drop for UserMapper {
             deallocate_page_frames(
                 PhysPageFrame::new(self.utable.table().phys()),
                 PageFrameCount::new(1),
-                &mut page_manager_lock_irqsave(),
             )
         };
     }
@@ -1152,12 +1152,35 @@ impl LockedVMA {
 
     pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) {
         // todo: 如果当前vma与文件相关,完善文件相关的逻辑
-
         let mut guard = self.lock_irqsave();
 
         // 获取物理页的anon_vma的守卫
         let mut page_manager_guard: SpinLockGuard<'_, crate::mm::page::PageManager> =
             page_manager_lock_irqsave();
+
+        // 获取映射的物理地址
+        if let Some((paddr, _flags)) = mapper.translate(guard.region().start()) {
+            // 如果是共享页,执行释放操作
+            let page = page_manager_guard.get(&paddr).unwrap();
+            let page_guard = page.read_irqsave();
+            if let PageType::Shm(shm_id) = page_guard.page_type() {
+                let mut shm_manager_guard = shm_manager_lock();
+                if let Some(kernel_shm) = shm_manager_guard.get_mut(shm_id) {
+                    // 更新最后一次断开连接时间
+                    kernel_shm.update_dtim();
+
+                    // 映射计数减少
+                    kernel_shm.decrease_count();
+
+                    // 释放shm_id
+                    if kernel_shm.map_count() == 0 && kernel_shm.mode().contains(ShmFlags::SHM_DEST)
+                    {
+                        shm_manager_guard.free_id(shm_id);
+                    }
+                }
+            }
+        }
+
         for page in guard.region.pages() {
             if mapper.translate(page.virt_address()).is_none() {
                 continue;
@@ -1167,18 +1190,13 @@ impl LockedVMA {
 
             // 从anon_vma中删除当前VMA
             let page = page_manager_guard.get_unwrap(&paddr);
-            page.write_irqsave().remove_vma(self);
-
-            // 如果物理页的anon_vma链表长度为0并且不是共享页,则释放物理页.
-            if page.read_irqsave().can_deallocate() {
-                unsafe {
-                    drop(page);
-                    deallocate_page_frames(
-                        PhysPageFrame::new(paddr),
-                        PageFrameCount::new(1),
-                        &mut page_manager_guard,
-                    )
-                };
+            let mut page_guard = page.write_irqsave();
+            page_guard.remove_vma(self);
+
+            // 如果物理页的vma链表长度为0并且未标记为不可回收,则释放物理页.
+            // TODO 后续由lru释放物理页面
+            if page_guard.can_deallocate() {
+                page_manager_guard.remove_page(&paddr);
             }
 
             flusher.consume(flush);
@@ -1659,9 +1677,7 @@ impl VMA {
         return Ok(r);
     }
 
-    pub fn page_address(&self, page: &Arc<Page>) -> Result<VirtAddr, SystemError> {
-        let page_guard = page.read_irqsave();
-        let index = page_guard.index().unwrap();
+    pub fn page_address(&self, index: usize) -> Result<VirtAddr, SystemError> {
         if index >= self.file_pgoff.unwrap() {
             let address =
                 self.region.start + ((index - self.file_pgoff.unwrap()) << MMArch::PAGE_SHIFT);

+ 14 - 14
kernel/src/perf/bpf.rs

@@ -1,14 +1,15 @@
 use super::{PerfEventOps, Result};
 use crate::arch::mm::LockedFrameAllocator;
 use crate::arch::MMArch;
-use crate::filesystem::vfs::file::PageCache;
+use crate::filesystem::page_cache::PageCache;
 use crate::filesystem::vfs::{FilePrivateData, FileSystem, IndexNode};
 use crate::include::bindings::linux_bpf::{
     perf_event_header, perf_event_mmap_page, perf_event_type,
 };
+use crate::libs::align::page_align_up;
 use crate::libs::spinlock::{SpinLock, SpinLockGuard};
-use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame};
-use crate::mm::page::{page_manager_lock_irqsave, Page};
+use crate::mm::allocator::page_frame::{PageFrameCount, PhysPageFrame};
+use crate::mm::page::{page_manager_lock_irqsave, PageFlags, PageType};
 use crate::mm::{MemoryManagementArch, PhysAddr};
 use crate::perf::util::{LostSamples, PerfProbeArgs, PerfSample, SampleHeader};
 use alloc::string::String;
@@ -240,18 +241,17 @@ impl BpfPerfEvent {
     }
     pub fn do_mmap(&self, _start: usize, len: usize, offset: usize) -> Result<()> {
         let mut data = self.data.lock();
-        // alloc page frame
-        let (phy_addr, page_count) =
-            unsafe { LockedFrameAllocator.allocate(PageFrameCount::new(len / PAGE_SIZE)) }
-                .ok_or(SystemError::ENOSPC)?;
         let mut page_manager_guard = page_manager_lock_irqsave();
-        let mut cur_phys = PhysPageFrame::new(phy_addr);
-        for i in 0..page_count.data() {
-            let page = Arc::new(Page::new(true, cur_phys.phys_address()));
-            let paddr = cur_phys.phys_address();
-            page_manager_guard.insert(paddr, &page);
-            data.page_cache.add_page(i, &page);
-            cur_phys = cur_phys.next();
+        let (phy_addr, pages) = page_manager_guard.create_pages(
+            PageType::Normal,
+            PageFlags::PG_UNEVICTABLE,
+            &mut LockedFrameAllocator,
+            PageFrameCount::new(page_align_up(len) / PAGE_SIZE),
+        )?;
+        for i in 0..pages.len() {
+            data.page_cache
+                .lock_irqsave()
+                .add_page(i, pages.get(i).unwrap());
         }
         let virt_addr = unsafe { MMArch::phys_2_virt(phy_addr) }.ok_or(SystemError::EFAULT)?;
         // create mmap page

+ 2 - 1
kernel/src/perf/kprobe.rs

@@ -5,7 +5,8 @@ use crate::bpf::helper::BPF_HELPER_FUN_SET;
 use crate::bpf::prog::BpfProg;
 use crate::debug::kprobe::args::KprobeInfo;
 use crate::debug::kprobe::{register_kprobe, unregister_kprobe, LockKprobe};
-use crate::filesystem::vfs::file::{File, PageCache};
+use crate::filesystem::page_cache::PageCache;
+use crate::filesystem::vfs::file::File;
 use crate::filesystem::vfs::{FilePrivateData, FileSystem, IndexNode};
 use crate::libs::casting::DowncastArc;
 use crate::libs::spinlock::SpinLockGuard;

+ 2 - 1
kernel/src/perf/mod.rs

@@ -2,7 +2,8 @@ mod bpf;
 mod kprobe;
 mod util;
 
-use crate::filesystem::vfs::file::{File, FileMode, PageCache};
+use crate::filesystem::page_cache::PageCache;
+use crate::filesystem::vfs::file::{File, FileMode};
 use crate::filesystem::vfs::syscall::ModeType;
 use crate::filesystem::vfs::{
     FilePrivateData, FileSystem, FileType, FsInfo, IndexNode, Metadata, SuperBlock,