-
-
Notifications
You must be signed in to change notification settings - Fork 161
实现页面反向映射 #670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
实现页面反向映射 #670
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,17 +6,88 @@ use core::{ | |
sync::atomic::{compiler_fence, Ordering}, | ||
}; | ||
|
||
use alloc::sync::Arc; | ||
use hashbrown::{HashMap, HashSet}; | ||
|
||
use crate::{ | ||
arch::{interrupt::ipi::send_ipi, MMArch}, | ||
exception::ipi::{IpiKind, IpiTarget}, | ||
kerror, kwarn, | ||
libs::spinlock::SpinLock, | ||
}; | ||
|
||
use super::{ | ||
allocator::page_frame::FrameAllocator, syscall::ProtFlags, MemoryManagementArch, PageTableKind, | ||
PhysAddr, VirtAddr, | ||
allocator::page_frame::FrameAllocator, syscall::ProtFlags, ucontext::LockedVMA, | ||
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, | ||
}; | ||
|
||
lazy_static! { | ||
/// 全局物理页信息管理器 | ||
pub static ref PAGE_MANAGER: SpinLock<PageManager> = SpinLock::new(PageManager::new()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这玩意应当显式指定初始化的时机,而不是使用lazy_static |
||
} | ||
|
||
// 物理页管理器 | ||
pub struct PageManager { | ||
phys2page: HashMap<PhysAddr, Page>, | ||
} | ||
|
||
impl PageManager { | ||
pub fn new() -> Self { | ||
Self { | ||
phys2page: HashMap::new(), | ||
} | ||
} | ||
|
||
pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page { | ||
self.phys2page.get_mut(paddr).unwrap() | ||
} | ||
|
||
pub fn insert(&mut self, paddr: PhysAddr, page: Page) { | ||
self.phys2page.insert(paddr, page); | ||
} | ||
|
||
pub fn remove_page(&mut self, paddr: &PhysAddr) { | ||
self.phys2page.remove(paddr); | ||
} | ||
} | ||
|
||
/// 物理页面信息 | ||
pub struct Page { | ||
/// 映射计数 | ||
map_count: usize, | ||
/// 是否为共享页 | ||
shared: bool, | ||
/// 映射到当前page的VMA | ||
anon_vma: HashSet<Arc<LockedVMA>>, | ||
} | ||
|
||
impl Page { | ||
pub fn new(shared: bool) -> Self { | ||
Self { | ||
map_count: 0, | ||
shared, | ||
anon_vma: HashSet::new(), | ||
} | ||
} | ||
|
||
/// 将vma加入anon_vma | ||
pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) { | ||
self.anon_vma.insert(vma); | ||
self.map_count += 1; | ||
} | ||
|
||
/// 将vma从anon_vma中删去 | ||
pub fn remove_vma(&mut self, vma: &LockedVMA) { | ||
self.anon_vma.remove(vma); | ||
self.map_count -= 1; | ||
} | ||
|
||
/// 判断当前物理页是否能被回 | ||
pub fn can_deallocate(&self) -> bool { | ||
self.map_count == 0 && !self.shared | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 也许这个map_count为0就能释放?不然的话如果忘记清除shared,就永远无法释放 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 我一开始也是这么想的,但是Linux的共享内存即使映射计数是0,在没有设置可被回收的情况下,是不会被释放的,进程依然能够连接到这块共享内存。或者看我们想怎么设计 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
哦哦哦,确实有道理。 |
||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct PageTable<Arch> { | ||
/// 当前页表表示的虚拟地址空间的起始地址 | ||
|
@@ -591,6 +662,8 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> { | |
compiler_fence(Ordering::SeqCst); | ||
let phys: PhysAddr = self.frame_allocator.allocate_one()?; | ||
compiler_fence(Ordering::SeqCst); | ||
|
||
PAGE_MANAGER.lock_irqsave().insert(phys, Page::new(false)); | ||
return self.map_phys(virt, phys, flags); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个
PAGE_MANAGER.lock()
最好封装成函数。并且应当是lock_irqsave?因为hzp在写的那个pagefault处理,估计中断上下文内会使用到这个东西,因此得lock irqsave