From f8cf44df4fe0707c7fb69ae98719153bb67e2ae5 Mon Sep 17 00:00:00 2001 From: MemoryShore <1353318529@qq.com> Date: Mon, 15 Apr 2024 04:53:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=A1=B5=E8=A1=A8=E6=8B=B7?= =?UTF-8?q?=E8=B4=9D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/mm/page.rs | 59 ++++++++++++++++++++++----------------- kernel/src/mm/ucontext.rs | 17 ++++++++--- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/kernel/src/mm/page.rs b/kernel/src/mm/page.rs index f348950ed..238ba7467 100644 --- a/kernel/src/mm/page.rs +++ b/kernel/src/mm/page.rs @@ -298,8 +298,16 @@ impl PageTable { )); } - // 克隆页表 - pub unsafe fn clone(&self, allocator: &mut impl FrameAllocator) -> Option> { + /// 拷贝页表 + /// ## 参数 + /// + /// - `allocator`: 物理页框分配器 + /// - `copy_on_write`: 是否写时复制 + pub unsafe fn clone( + &self, + allocator: &mut impl FrameAllocator, + copy_on_write: bool, + ) -> Option> { // 分配新页面作为新的页表 let phys = allocator.allocate_one()?; let frame = MMArch::phys_2_virt(phys).unwrap(); @@ -309,33 +317,33 @@ impl PageTable { for i in 0..Arch::PAGE_ENTRY_NUM { if let Some(mut entry) = self.entry(i) { if entry.present() { - let mut new_flags = entry.flags().set_write(false); - entry.set_flags(new_flags); - self.set_entry(i, entry); - new_flags = new_flags.set_dirty(false); - entry.set_flags(new_flags); - new_table.set_entry(i, entry); + if copy_on_write { + let mut new_flags = entry.flags().set_write(false); + entry.set_flags(new_flags); + self.set_entry(i, entry); + new_flags = new_flags.set_dirty(false); + entry.set_flags(new_flags); + new_table.set_entry(i, entry); + } else { + let phys = allocator.allocate_one()?; + let mut anon_vma_guard = page_manager_lock_irqsave(); + anon_vma_guard.insert(phys, Page::new(false)); + 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, + ); + new_table.set_entry(i, PageEntry::new(phys, entry.flags())); + } } - - // if entry.present() { - // let phys = allocator.allocate_one()?; - // let mut anon_vma_guard = page_manager_lock_irqsave(); - // anon_vma_guard.insert(phys, Page::new(false)); - // 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, - // ); - // new_table.set_entry(i, PageEntry::new(phys, entry.flags())); - // } } } } else { // 非一级页表拷贝时,对每个页表项对应的页表都进行拷贝 for i in 0..MMArch::PAGE_ENTRY_NUM { if let Some(next_table) = self.next_level_table(i) { - let table = next_table.clone(allocator)?; + let table = next_table.clone(allocator, copy_on_write)?; let old_entry = self.entry(i).unwrap(); let entry = PageEntry::new(table.phys(), old_entry.flags()); new_table.set_entry(i, entry); @@ -689,7 +697,7 @@ impl PageFlags { /// /// ## 参数 /// - /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 + /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 #[inline(always)] pub fn set_access(self, value: bool) -> Self { return self.update_flags(Arch::ENTRY_FLAG_ACCESSED, value); @@ -1071,14 +1079,15 @@ impl PageMapper { /// ## 参数 /// /// - `umapper`: 要拷贝的用户空间 - pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self) { + /// - `copy_on_write`: 是否写时复制 + pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) { let old_table = umapper.table(); let new_table = self.table(); let allocator = self.allocator_mut(); // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射 for entry_index in 0..Arch::PAGE_KERNEL_INDEX { if let Some(next_table) = old_table.next_level_table(entry_index) { - let table = next_table.clone(allocator).unwrap(); + let table = next_table.clone(allocator, copy_on_write).unwrap(); let old_entry = old_table.entry(entry_index).unwrap(); let entry = PageEntry::new(table.phys(), old_entry.flags()); new_table.set_entry(entry_index, entry); diff --git a/kernel/src/mm/ucontext.rs b/kernel/src/mm/ucontext.rs index 172a50ff8..94a893bcc 100644 --- a/kernel/src/mm/ucontext.rs +++ b/kernel/src/mm/ucontext.rs @@ -160,7 +160,11 @@ impl InnerAddressSpace { let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let new_addr_space = AddressSpace::new(false)?; let mut new_guard = new_addr_space.write(); - unsafe { new_guard.user_mapper.clone_from(&mut self.user_mapper) }; + unsafe { + new_guard + .user_mapper + .clone_from(&mut self.user_mapper, true) + }; // 拷贝用户栈的结构体信息,但是不拷贝用户栈的内容(因为后面VMA的拷贝会拷贝用户栈的内容) unsafe { @@ -708,9 +712,14 @@ impl UserMapper { return Self { utable }; } - // 拷贝用户空间映射 - pub unsafe fn clone_from(&mut self, umapper: &mut Self) { - self.utable.clone_user_mapping(&mut umapper.utable); + /// 拷贝用户空间映射 + /// ## 参数 + /// + /// - `umapper`: 要拷贝的用户空间 + /// - `copy_on_write`: 是否写时复制 + pub unsafe fn clone_from(&mut self, umapper: &mut Self, copy_on_write: bool) { + self.utable + .clone_user_mapping(&mut umapper.utable, copy_on_write); } }