1 // 进程的用户空间内存管理 2 3 use core::{ 4 cmp, 5 hash::Hasher, 6 intrinsics::unlikely, 7 ops::Add, 8 sync::atomic::{compiler_fence, Ordering}, 9 }; 10 11 use alloc::{ 12 collections::BTreeMap, 13 sync::{Arc, Weak}, 14 vec::Vec, 15 }; 16 use hashbrown::HashSet; 17 18 use crate::{ 19 arch::{mm::PageMapper, CurrentIrqArch, MMArch}, 20 exception::InterruptArch, 21 libs::{ 22 align::page_align_up, 23 rwlock::{RwLock, RwLockWriteGuard}, 24 spinlock::{SpinLock, SpinLockGuard}, 25 }, 26 process::ProcessManager, 27 syscall::SystemError, 28 }; 29 30 use super::{ 31 allocator::page_frame::{ 32 deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter, 33 }, 34 page::{Flusher, InactiveFlusher, PageFlags, PageFlushAll}, 35 syscall::{MapFlags, ProtFlags}, 36 MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion, 37 }; 38 39 /// MMAP_MIN_ADDR的默认值 40 /// 以下内容来自linux-5.19: 41 /// This is the portion of low virtual memory which should be protected 42 // from userspace allocation. Keeping a user from writing to low pages 43 // can help reduce the impact of kernel NULL pointer bugs. 44 // For most ia64, ppc64 and x86 users with lots of address space 45 // a value of 65536 is reasonable and should cause no problems. 46 // On arm and other archs it should not be higher than 32768. 47 // Programs which use vm86 functionality or have some need to map 48 // this low address space will need CAP_SYS_RAWIO or disable this 49 // protection by setting the value to 0. 50 pub const DEFAULT_MMAP_MIN_ADDR: usize = 65536; 51 52 #[derive(Debug)] 53 pub struct AddressSpace { 54 inner: RwLock<InnerAddressSpace>, 55 } 56 57 impl AddressSpace { 58 pub fn new(create_stack: bool) -> Result<Arc<Self>, SystemError> { 59 let inner = InnerAddressSpace::new(create_stack)?; 60 let result = Self { 61 inner: RwLock::new(inner), 62 }; 63 return Ok(Arc::new(result)); 64 } 65 66 /// 从pcb中获取当前进程的地址空间结构体的Arc指针 67 pub fn current() -> Result<Arc<AddressSpace>, SystemError> { 68 let vm = ProcessManager::current_pcb() 69 .basic() 70 .user_vm() 71 .expect("Current process has no address space"); 72 73 return Ok(vm); 74 } 75 76 /// 判断某个地址空间是否为当前进程的地址空间 77 pub fn is_current(self: &Arc<Self>) -> bool { 78 let current = Self::current(); 79 if let Ok(current) = current { 80 return Arc::ptr_eq(¤t, self); 81 } 82 return false; 83 } 84 } 85 86 impl core::ops::Deref for AddressSpace { 87 type Target = RwLock<InnerAddressSpace>; 88 89 fn deref(&self) -> &Self::Target { 90 &self.inner 91 } 92 } 93 94 impl core::ops::DerefMut for AddressSpace { 95 fn deref_mut(&mut self) -> &mut Self::Target { 96 &mut self.inner 97 } 98 } 99 100 /// @brief 用户地址空间结构体(每个进程都有一个) 101 #[derive(Debug)] 102 pub struct InnerAddressSpace { 103 pub user_mapper: UserMapper, 104 pub mappings: UserMappings, 105 pub mmap_min: VirtAddr, 106 /// 用户栈信息结构体 107 pub user_stack: Option<UserStack>, 108 109 pub elf_brk_start: VirtAddr, 110 pub elf_brk: VirtAddr, 111 112 /// 当前进程的堆空间的起始地址 113 pub brk_start: VirtAddr, 114 /// 当前进程的堆空间的结束地址(不包含) 115 pub brk: VirtAddr, 116 117 pub start_code: VirtAddr, 118 pub end_code: VirtAddr, 119 pub start_data: VirtAddr, 120 pub end_data: VirtAddr, 121 } 122 123 impl InnerAddressSpace { 124 pub fn new(create_stack: bool) -> Result<Self, SystemError> { 125 let mut result = Self { 126 user_mapper: MMArch::setup_new_usermapper()?, 127 mappings: UserMappings::new(), 128 mmap_min: VirtAddr(DEFAULT_MMAP_MIN_ADDR), 129 elf_brk_start: VirtAddr::new(0), 130 elf_brk: VirtAddr::new(0), 131 brk_start: MMArch::USER_BRK_START, 132 brk: MMArch::USER_BRK_START, 133 user_stack: None, 134 start_code: VirtAddr(0), 135 end_code: VirtAddr(0), 136 start_data: VirtAddr(0), 137 end_data: VirtAddr(0), 138 }; 139 if create_stack { 140 // kdebug!("to create user stack."); 141 result.new_user_stack(UserStack::DEFAULT_USER_STACK_SIZE)?; 142 } 143 144 return Ok(result); 145 } 146 147 /// 尝试克隆当前进程的地址空间,包括这些映射都会被克隆 148 /// 149 /// # Returns 150 /// 151 /// 返回克隆后的,新的地址空间的Arc指针 152 pub fn try_clone(&mut self) -> Result<Arc<AddressSpace>, SystemError> { 153 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 154 let new_addr_space = AddressSpace::new(false)?; 155 let mut new_guard = new_addr_space.write(); 156 157 // 拷贝用户栈的结构体信息,但是不拷贝用户栈的内容(因为后面VMA的拷贝会拷贝用户栈的内容) 158 unsafe { 159 new_guard.user_stack = Some(self.user_stack.as_ref().unwrap().clone_info_only()); 160 } 161 let _current_stack_size = self.user_stack.as_ref().unwrap().stack_size(); 162 163 let current_mapper = &mut self.user_mapper.utable; 164 165 for vma in self.mappings.vmas.iter() { 166 // TODO: 增加对VMA是否为文件映射的判断,如果是的话,就跳过 167 168 let vma_guard: SpinLockGuard<'_, VMA> = vma.lock(); 169 let old_flags = vma_guard.flags(); 170 let tmp_flags: PageFlags<MMArch> = PageFlags::new().set_write(true); 171 172 // 分配内存页并创建新的VMA 173 let new_vma = VMA::zeroed( 174 VirtPageFrame::new(vma_guard.region.start()), 175 PageFrameCount::new(vma_guard.region.size() / MMArch::PAGE_SIZE), 176 tmp_flags, 177 &mut new_guard.user_mapper.utable, 178 (), 179 )?; 180 new_guard.mappings.vmas.insert(new_vma.clone()); 181 // kdebug!("new vma: {:x?}", new_vma); 182 let mut new_vma_guard = new_vma.lock(); 183 for page in new_vma_guard.pages().map(|p| p.virt_address()) { 184 // kdebug!("page: {:x?}", page); 185 let current_frame = unsafe { 186 MMArch::phys_2_virt( 187 current_mapper 188 .translate(page) 189 .expect("VMA page not mapped") 190 .0, 191 ) 192 } 193 .expect("Phys2Virt: vaddr overflow.") 194 .data() as *mut u8; 195 196 let new_frame = unsafe { 197 MMArch::phys_2_virt( 198 new_guard 199 .user_mapper 200 .utable 201 .translate(page) 202 .expect("VMA page not mapped") 203 .0, 204 ) 205 } 206 .expect("Phys2Virt: vaddr overflow.") 207 .data() as *mut u8; 208 209 unsafe { 210 // 拷贝数据 211 new_frame.copy_from_nonoverlapping(current_frame, MMArch::PAGE_SIZE); 212 } 213 } 214 drop(vma_guard); 215 216 new_vma_guard.remap(old_flags, &mut new_guard.user_mapper.utable, ())?; 217 drop(new_vma_guard); 218 } 219 drop(new_guard); 220 drop(irq_guard); 221 return Ok(new_addr_space); 222 } 223 224 /// 判断当前的地址空间是否是当前进程的地址空间 225 #[inline] 226 pub fn is_current(&self) -> bool { 227 return self.user_mapper.utable.is_current(); 228 } 229 230 /// 进行匿名页映射 231 /// 232 /// ## 参数 233 /// 234 /// - `start_vaddr`:映射的起始地址 235 /// - `len`:映射的长度 236 /// - `prot_flags`:保护标志 237 /// - `map_flags`:映射标志 238 /// - `round_to_min`:是否将`start_vaddr`对齐到`mmap_min`,如果为`true`,则当`start_vaddr`不为0时,会对齐到`mmap_min`,否则仅向下对齐到页边界 239 /// 240 /// ## 返回 241 /// 242 /// 返回映射的起始虚拟页帧 243 pub fn map_anonymous( 244 &mut self, 245 start_vaddr: VirtAddr, 246 len: usize, 247 prot_flags: ProtFlags, 248 map_flags: MapFlags, 249 round_to_min: bool, 250 ) -> Result<VirtPageFrame, SystemError> { 251 // 用于对齐hint的函数 252 let round_hint_to_min = |hint: VirtAddr| { 253 // 先把hint向下对齐到页边界 254 let addr = hint.data() & (!MMArch::PAGE_OFFSET_MASK); 255 // kdebug!("map_anonymous: hint = {:?}, addr = {addr:#x}", hint); 256 // 如果hint不是0,且hint小于DEFAULT_MMAP_MIN_ADDR,则对齐到DEFAULT_MMAP_MIN_ADDR 257 if (addr != 0) && round_to_min && (addr < DEFAULT_MMAP_MIN_ADDR) { 258 Some(VirtAddr::new(page_align_up(DEFAULT_MMAP_MIN_ADDR))) 259 } else if addr == 0 { 260 None 261 } else { 262 Some(VirtAddr::new(addr)) 263 } 264 }; 265 // kdebug!("map_anonymous: start_vaddr = {:?}", start_vaddr); 266 // kdebug!("map_anonymous: len(no align) = {}", len); 267 268 let len = page_align_up(len); 269 270 // kdebug!("map_anonymous: len = {}", len); 271 272 let start_page: VirtPageFrame = self.mmap( 273 round_hint_to_min(start_vaddr), 274 PageFrameCount::from_bytes(len).unwrap(), 275 prot_flags, 276 map_flags, 277 move |page, count, flags, mapper, flusher| { 278 Ok(VMA::zeroed(page, count, flags, mapper, flusher)?) 279 }, 280 )?; 281 282 return Ok(start_page); 283 } 284 285 /// 向进程的地址空间映射页面 286 /// 287 /// # 参数 288 /// 289 /// - `addr`:映射的起始地址,如果为`None`,则由内核自动分配 290 /// - `page_count`:映射的页面数量 291 /// - `prot_flags`:保护标志 292 /// - `map_flags`:映射标志 293 /// - `map_func`:映射函数,用于创建VMA 294 /// 295 /// # Returns 296 /// 297 /// 返回映射的起始虚拟页帧 298 /// 299 /// # Errors 300 /// 301 /// - `EINVAL`:参数错误 302 pub fn mmap< 303 F: FnOnce( 304 VirtPageFrame, 305 PageFrameCount, 306 PageFlags<MMArch>, 307 &mut PageMapper, 308 &mut dyn Flusher<MMArch>, 309 ) -> Result<Arc<LockedVMA>, SystemError>, 310 >( 311 &mut self, 312 addr: Option<VirtAddr>, 313 page_count: PageFrameCount, 314 prot_flags: ProtFlags, 315 map_flags: MapFlags, 316 map_func: F, 317 ) -> Result<VirtPageFrame, SystemError> { 318 if page_count == PageFrameCount::new(0) { 319 return Err(SystemError::EINVAL); 320 } 321 // kdebug!("mmap: addr: {addr:?}, page_count: {page_count:?}, prot_flags: {prot_flags:?}, map_flags: {map_flags:?}"); 322 323 // 找到未使用的区域 324 let region = match addr { 325 Some(vaddr) => { 326 self.mappings 327 .find_free_at(self.mmap_min, vaddr, page_count.bytes(), map_flags)? 328 } 329 None => self 330 .mappings 331 .find_free(self.mmap_min, page_count.bytes()) 332 .ok_or(SystemError::ENOMEM)?, 333 }; 334 335 let page = VirtPageFrame::new(region.start()); 336 337 // kdebug!("mmap: page: {:?}, region={region:?}", page.virt_address()); 338 339 compiler_fence(Ordering::SeqCst); 340 let (mut active, mut inactive); 341 let flusher = if self.is_current() { 342 active = PageFlushAll::new(); 343 &mut active as &mut dyn Flusher<MMArch> 344 } else { 345 inactive = InactiveFlusher::new(); 346 &mut inactive as &mut dyn Flusher<MMArch> 347 }; 348 compiler_fence(Ordering::SeqCst); 349 // 映射页面,并将VMA插入到地址空间的VMA列表中 350 self.mappings.insert_vma(map_func( 351 page, 352 page_count, 353 PageFlags::from_prot_flags(prot_flags, true), 354 &mut self.user_mapper.utable, 355 flusher, 356 )?); 357 358 return Ok(page); 359 } 360 361 /// 取消进程的地址空间中的映射 362 /// 363 /// # 参数 364 /// 365 /// - `start_page`:起始页帧 366 /// - `page_count`:取消映射的页帧数量 367 /// 368 /// # Errors 369 /// 370 /// - `EINVAL`:参数错误 371 /// - `ENOMEM`:内存不足 372 pub fn munmap( 373 &mut self, 374 start_page: VirtPageFrame, 375 page_count: PageFrameCount, 376 ) -> Result<(), SystemError> { 377 let to_unmap = VirtRegion::new(start_page.virt_address(), page_count.bytes()); 378 let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 379 380 let regions: Vec<Arc<LockedVMA>> = self.mappings.conflicts(to_unmap).collect::<Vec<_>>(); 381 382 for r in regions { 383 let r = r.lock().region; 384 let r = self.mappings.remove_vma(&r).unwrap(); 385 let intersection = r.lock().region().intersect(&to_unmap).unwrap(); 386 let (before, r, after) = r.extract(intersection).unwrap(); 387 388 // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑 389 390 if let Some(before) = before { 391 // 如果前面有VMA,则需要将前面的VMA重新插入到地址空间的VMA列表中 392 self.mappings.insert_vma(before); 393 } 394 395 if let Some(after) = after { 396 // 如果后面有VMA,则需要将后面的VMA重新插入到地址空间的VMA列表中 397 self.mappings.insert_vma(after); 398 } 399 400 r.unmap(&mut self.user_mapper.utable, &mut flusher); 401 } 402 403 // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑 404 405 return Ok(()); 406 } 407 408 pub fn mprotect( 409 &mut self, 410 start_page: VirtPageFrame, 411 page_count: PageFrameCount, 412 prot_flags: ProtFlags, 413 ) -> Result<(), SystemError> { 414 // kdebug!( 415 // "mprotect: start_page: {:?}, page_count: {:?}, prot_flags:{prot_flags:?}", 416 // start_page, 417 // page_count 418 // ); 419 let (mut active, mut inactive); 420 let mut flusher = if self.is_current() { 421 active = PageFlushAll::new(); 422 &mut active as &mut dyn Flusher<MMArch> 423 } else { 424 inactive = InactiveFlusher::new(); 425 &mut inactive as &mut dyn Flusher<MMArch> 426 }; 427 428 let mapper = &mut self.user_mapper.utable; 429 let region = VirtRegion::new(start_page.virt_address(), page_count.bytes()); 430 // kdebug!("mprotect: region: {:?}", region); 431 432 let regions = self.mappings.conflicts(region).collect::<Vec<_>>(); 433 // kdebug!("mprotect: regions: {:?}", regions); 434 435 for r in regions { 436 // kdebug!("mprotect: r: {:?}", r); 437 let r = r.lock().region().clone(); 438 let r = self.mappings.remove_vma(&r).unwrap(); 439 440 let intersection = r.lock().region().intersect(®ion).unwrap(); 441 let (before, r, after) = r.extract(intersection).expect("Failed to extract VMA"); 442 443 if let Some(before) = before { 444 self.mappings.insert_vma(before); 445 } 446 if let Some(after) = after { 447 self.mappings.insert_vma(after); 448 } 449 450 let mut r_guard = r.lock(); 451 // 如果VMA的保护标志不允许指定的修改,则返回错误 452 if !r_guard.can_have_flags(prot_flags) { 453 drop(r_guard); 454 self.mappings.insert_vma(r.clone()); 455 return Err(SystemError::EACCES); 456 } 457 458 let new_flags: PageFlags<MMArch> = r_guard 459 .flags() 460 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC)) 461 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE)); 462 463 r_guard.remap(new_flags, mapper, &mut flusher)?; 464 drop(r_guard); 465 self.mappings.insert_vma(r); 466 } 467 468 return Ok(()); 469 } 470 471 /// 创建新的用户栈 472 /// 473 /// ## 参数 474 /// 475 /// - `size`:栈的大小 476 pub fn new_user_stack(&mut self, size: usize) -> Result<(), SystemError> { 477 assert!(self.user_stack.is_none(), "User stack already exists"); 478 let stack = UserStack::new(self, None, size)?; 479 self.user_stack = Some(stack); 480 return Ok(()); 481 } 482 483 #[inline(always)] 484 pub fn user_stack_mut(&mut self) -> Option<&mut UserStack> { 485 return self.user_stack.as_mut(); 486 } 487 488 /// 取消用户空间内的所有映射 489 pub unsafe fn unmap_all(&mut self) { 490 let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 491 for vma in self.mappings.iter_vmas() { 492 vma.unmap(&mut self.user_mapper.utable, &mut flusher); 493 } 494 } 495 496 /// 设置进程的堆的内存空间 497 /// 498 /// ## 参数 499 /// 500 /// - `new_brk`:新的堆的结束地址。需要满足页对齐要求,并且是用户空间地址,且大于等于当前的堆的起始地址 501 /// 502 /// ## 返回值 503 /// 504 /// 返回旧的堆的结束地址 505 pub unsafe fn set_brk(&mut self, new_brk: VirtAddr) -> Result<VirtAddr, SystemError> { 506 assert!(new_brk.check_aligned(MMArch::PAGE_SIZE)); 507 508 if !new_brk.check_user() || new_brk < self.brk_start { 509 return Err(SystemError::EFAULT); 510 } 511 512 let old_brk = self.brk; 513 514 if new_brk > self.brk { 515 let len = new_brk - self.brk; 516 let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 517 let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED; 518 self.map_anonymous(old_brk, len, prot_flags, map_flags, true)?; 519 520 self.brk = new_brk; 521 return Ok(old_brk); 522 } else { 523 let unmap_len = self.brk - new_brk; 524 let unmap_start = new_brk; 525 if unmap_len == 0 { 526 return Ok(old_brk); 527 } 528 self.munmap( 529 VirtPageFrame::new(unmap_start), 530 PageFrameCount::from_bytes(unmap_len).unwrap(), 531 )?; 532 self.brk = new_brk; 533 return Ok(old_brk); 534 } 535 } 536 537 pub unsafe fn sbrk(&mut self, incr: isize) -> Result<VirtAddr, SystemError> { 538 if incr == 0 { 539 return Ok(self.brk); 540 } 541 542 let new_brk = if incr > 0 { 543 self.brk + incr as usize 544 } else { 545 self.brk - (incr.abs() as usize) 546 }; 547 548 let new_brk = VirtAddr::new(page_align_up(new_brk.data())); 549 550 return self.set_brk(new_brk); 551 } 552 } 553 554 impl Drop for InnerAddressSpace { 555 fn drop(&mut self) { 556 unsafe { 557 self.unmap_all(); 558 } 559 } 560 } 561 562 #[derive(Debug, Hash)] 563 pub struct UserMapper { 564 pub utable: PageMapper, 565 } 566 567 impl UserMapper { 568 pub fn new(utable: PageMapper) -> Self { 569 return Self { utable }; 570 } 571 } 572 573 impl Drop for UserMapper { 574 fn drop(&mut self) { 575 if self.utable.is_current() { 576 // 如果当前要被销毁的用户空间的页表是当前进程的页表,那么就切换回初始内核页表 577 unsafe { MMArch::set_table(PageTableKind::User, MMArch::initial_page_table()) } 578 } 579 // 释放用户空间顶层页表占用的页帧 580 // 请注意,在释放这个页帧之前,用户页表应该已经被完全释放,否则会产生内存泄露 581 unsafe { 582 deallocate_page_frames( 583 PhysPageFrame::new(self.utable.table().phys()), 584 PageFrameCount::new(1), 585 ) 586 }; 587 } 588 } 589 590 /// 用户空间映射信息 591 #[derive(Debug)] 592 pub struct UserMappings { 593 /// 当前用户空间的虚拟内存区域 594 vmas: HashSet<Arc<LockedVMA>>, 595 /// 当前用户空间的VMA空洞 596 vm_holes: BTreeMap<VirtAddr, usize>, 597 } 598 599 impl UserMappings { 600 pub fn new() -> Self { 601 return Self { 602 vmas: HashSet::new(), 603 vm_holes: core::iter::once((VirtAddr::new(0), MMArch::USER_END_VADDR.data())) 604 .collect::<BTreeMap<_, _>>(), 605 }; 606 } 607 608 /// 判断当前进程的VMA内,是否有包含指定的虚拟地址的VMA。 609 /// 610 /// 如果有,返回包含指定虚拟地址的VMA的Arc指针,否则返回None。 611 #[allow(dead_code)] 612 pub fn contains(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> { 613 for v in self.vmas.iter() { 614 let guard = v.lock(); 615 if guard.region.contains(vaddr) { 616 return Some(v.clone()); 617 } 618 } 619 return None; 620 } 621 622 /// 获取当前进程的地址空间中,与给定虚拟地址范围有重叠的VMA的迭代器。 623 pub fn conflicts(&self, request: VirtRegion) -> impl Iterator<Item = Arc<LockedVMA>> + '_ { 624 let r = self 625 .vmas 626 .iter() 627 .filter(move |v| !v.lock().region.intersect(&request).is_none()) 628 .cloned(); 629 return r; 630 } 631 632 /// 在当前进程的地址空间中,寻找第一个符合条件的空闲的虚拟内存范围。 633 /// 634 /// @param min_vaddr 最小的起始地址 635 /// @param size 请求的大小 636 /// 637 /// @return 如果找到了,返回虚拟内存范围,否则返回None 638 pub fn find_free(&self, min_vaddr: VirtAddr, size: usize) -> Option<VirtRegion> { 639 let _vaddr = min_vaddr; 640 let mut iter = self 641 .vm_holes 642 .iter() 643 .skip_while(|(hole_vaddr, hole_size)| hole_vaddr.add(**hole_size) <= min_vaddr); 644 645 let (hole_vaddr, size) = iter.find(|(hole_vaddr, hole_size)| { 646 // 计算当前空洞的可用大小 647 let available_size: usize = 648 if hole_vaddr <= &&min_vaddr && min_vaddr <= hole_vaddr.add(**hole_size) { 649 **hole_size - (min_vaddr - **hole_vaddr) 650 } else { 651 **hole_size 652 }; 653 654 size <= available_size 655 })?; 656 657 // 创建一个新的虚拟内存范围。 658 let region = VirtRegion::new(cmp::max(*hole_vaddr, min_vaddr), *size); 659 return Some(region); 660 } 661 662 pub fn find_free_at( 663 &self, 664 min_vaddr: VirtAddr, 665 vaddr: VirtAddr, 666 size: usize, 667 flags: MapFlags, 668 ) -> Result<VirtRegion, SystemError> { 669 // 如果没有指定地址,那么就在当前进程的地址空间中寻找一个空闲的虚拟内存范围。 670 if vaddr == VirtAddr::new(0) { 671 return self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM); 672 } 673 674 // 如果指定了地址,那么就检查指定的地址是否可用。 675 676 let requested = VirtRegion::new(vaddr, size); 677 678 if requested.end() >= MMArch::USER_END_VADDR || !vaddr.check_aligned(MMArch::PAGE_SIZE) { 679 return Err(SystemError::EINVAL); 680 } 681 682 if let Some(_x) = self.conflicts(requested).next() { 683 if flags.contains(MapFlags::MAP_FIXED_NOREPLACE) { 684 // 如果指定了 MAP_FIXED_NOREPLACE 标志,由于所指定的地址无法成功建立映射,则放弃映射,不对地址做修正 685 return Err(SystemError::EEXIST); 686 } 687 688 if flags.contains(MapFlags::MAP_FIXED) { 689 // todo: 支持MAP_FIXED标志对已有的VMA进行覆盖 690 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 691 } 692 693 // 如果没有指定MAP_FIXED标志,那么就对地址做修正 694 let requested = self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM)?; 695 return Ok(requested); 696 } 697 698 return Ok(requested); 699 } 700 701 /// 在当前进程的地址空间中,保留一个指定大小的区域,使得该区域不在空洞中。 702 /// 该函数会修改vm_holes中的空洞信息。 703 /// 704 /// @param region 要保留的区域 705 /// 706 /// 请注意,在调用本函数之前,必须先确定region所在范围内没有VMA。 707 fn reserve_hole(&mut self, region: &VirtRegion) { 708 let prev_hole: Option<(&VirtAddr, &mut usize)> = 709 self.vm_holes.range_mut(..=region.start()).next_back(); 710 711 if let Some((prev_hole_vaddr, prev_hole_size)) = prev_hole { 712 let prev_hole_end = prev_hole_vaddr.add(*prev_hole_size); 713 714 if prev_hole_end > region.start() { 715 // 如果前一个空洞的结束地址大于当前空洞的起始地址,那么就需要调整前一个空洞的大小。 716 *prev_hole_size = region.start().data() - prev_hole_vaddr.data(); 717 } 718 719 if prev_hole_end > region.end() { 720 // 如果前一个空洞的结束地址大于当前空洞的结束地址,那么就需要增加一个新的空洞。 721 self.vm_holes 722 .insert(region.end(), prev_hole_end - region.end()); 723 } 724 } 725 } 726 727 /// 在当前进程的地址空间中,释放一个指定大小的区域,使得该区域成为一个空洞。 728 /// 该函数会修改vm_holes中的空洞信息。 729 fn unreserve_hole(&mut self, region: &VirtRegion) { 730 // 如果将要插入的空洞与后一个空洞相邻,那么就需要合并。 731 let next_hole_size: Option<usize> = self.vm_holes.remove(®ion.end()); 732 733 if let Some((_prev_hole_vaddr, prev_hole_size)) = self 734 .vm_holes 735 .range_mut(..region.start()) 736 .next_back() 737 .filter(|(offset, size)| offset.data() + **size == region.start().data()) 738 { 739 *prev_hole_size += region.size() + next_hole_size.unwrap_or(0); 740 } else { 741 self.vm_holes 742 .insert(region.start(), region.size() + next_hole_size.unwrap_or(0)); 743 } 744 } 745 746 /// 在当前进程的映射关系中,插入一个新的VMA。 747 pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) { 748 let region = vma.lock().region.clone(); 749 // 要求插入的地址范围必须是空闲的,也就是说,当前进程的地址空间中,不能有任何与之重叠的VMA。 750 assert!(self.conflicts(region).next().is_none()); 751 self.reserve_hole(®ion); 752 753 self.vmas.insert(vma); 754 } 755 756 /// @brief 删除一个VMA,并把对应的地址空间加入空洞中。 757 /// 758 /// 这里不会取消VMA对应的地址的映射 759 /// 760 /// @param region 要删除的VMA所在的地址范围 761 /// 762 /// @return 如果成功删除了VMA,则返回被删除的VMA,否则返回None 763 /// 如果没有可以删除的VMA,则不会执行删除操作,并报告失败。 764 pub fn remove_vma(&mut self, region: &VirtRegion) -> Option<Arc<LockedVMA>> { 765 // 请注意,由于这里会对每个VMA加锁,因此性能很低 766 let vma: Arc<LockedVMA> = self 767 .vmas 768 .drain_filter(|vma| vma.lock().region == *region) 769 .next()?; 770 self.unreserve_hole(region); 771 772 return Some(vma); 773 } 774 775 /// @brief Get the iterator of all VMAs in this process. 776 pub fn iter_vmas(&self) -> hashbrown::hash_set::Iter<Arc<LockedVMA>> { 777 return self.vmas.iter(); 778 } 779 } 780 781 impl Default for UserMappings { 782 fn default() -> Self { 783 return Self::new(); 784 } 785 } 786 787 /// 加了锁的VMA 788 /// 789 /// 备注:进行性能测试,看看SpinLock和RwLock哪个更快。 790 #[derive(Debug)] 791 pub struct LockedVMA(SpinLock<VMA>); 792 793 impl core::hash::Hash for LockedVMA { 794 fn hash<H: Hasher>(&self, state: &mut H) { 795 self.0.lock().hash(state); 796 } 797 } 798 799 impl PartialEq for LockedVMA { 800 fn eq(&self, other: &Self) -> bool { 801 self.0.lock().eq(&other.0.lock()) 802 } 803 } 804 805 impl Eq for LockedVMA {} 806 807 #[allow(dead_code)] 808 impl LockedVMA { 809 pub fn new(vma: VMA) -> Arc<Self> { 810 let r = Arc::new(Self(SpinLock::new(vma))); 811 r.0.lock().self_ref = Arc::downgrade(&r); 812 return r; 813 } 814 815 pub fn lock(&self) -> SpinLockGuard<VMA> { 816 return self.0.lock(); 817 } 818 819 /// 调整当前VMA的页面的标志位 820 /// 821 /// TODO:增加调整虚拟页映射的物理地址的功能 822 /// 823 /// @param flags 新的标志位 824 /// @param mapper 页表映射器 825 /// @param flusher 页表项刷新器 826 /// 827 pub fn remap( 828 &self, 829 flags: PageFlags<MMArch>, 830 mapper: &mut PageMapper, 831 mut flusher: impl Flusher<MMArch>, 832 ) -> Result<(), SystemError> { 833 let mut guard = self.lock(); 834 assert!(guard.mapped); 835 for page in guard.region.pages() { 836 // 暂时要求所有的页帧都已经映射到页表 837 // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了 838 let r = unsafe { 839 mapper 840 .remap(page.virt_address(), flags) 841 .expect("Failed to remap, beacuse of some page is not mapped") 842 }; 843 flusher.consume(r); 844 } 845 guard.flags = flags; 846 return Ok(()); 847 } 848 849 pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) { 850 // todo: 如果当前vma与文件相关,完善文件相关的逻辑 851 852 let mut guard = self.lock(); 853 assert!(guard.mapped); 854 for page in guard.region.pages() { 855 let (paddr, _, flush) = unsafe { mapper.unmap_phys(page.virt_address(), true) } 856 .expect("Failed to unmap, beacuse of some page is not mapped"); 857 858 // todo: 获取物理页的anon_vma的守卫 859 860 // todo: 从anon_vma中删除当前VMA 861 862 // todo: 如果物理页的anon_vma链表长度为0,则释放物理页. 863 864 // 目前由于还没有实现共享页,所以直接释放物理页也没问题。 865 // 但是在实现共享页之后,就不能直接释放物理页了,需要在anon_vma链表长度为0的时候才能释放物理页 866 unsafe { deallocate_page_frames(PhysPageFrame::new(paddr), PageFrameCount::new(1)) }; 867 868 flusher.consume(flush); 869 } 870 guard.mapped = false; 871 } 872 873 pub fn mapped(&self) -> bool { 874 return self.0.lock().mapped; 875 } 876 877 /// 将当前VMA进行切分,切分成3个VMA,分别是: 878 /// 879 /// 1. 前面的VMA,如果没有则为None 880 /// 2. 中间的VMA,也就是传入的Region 881 /// 3. 后面的VMA,如果没有则为None 882 pub fn extract( 883 &self, 884 region: VirtRegion, 885 ) -> Option<( 886 Option<Arc<LockedVMA>>, 887 Arc<LockedVMA>, 888 Option<Arc<LockedVMA>>, 889 )> { 890 assert!(region.start().check_aligned(MMArch::PAGE_SIZE)); 891 assert!(region.end().check_aligned(MMArch::PAGE_SIZE)); 892 893 let mut guard = self.lock(); 894 { 895 // 如果传入的region不在当前VMA的范围内,则直接返回None 896 if unlikely(region.start() < guard.region.start() || region.end() > guard.region.end()) 897 { 898 return None; 899 } 900 901 let intersect: Option<VirtRegion> = guard.region.intersect(®ion); 902 // 如果当前VMA不包含region,则直接返回None 903 if unlikely(intersect.is_none()) { 904 return None; 905 } 906 let intersect: VirtRegion = intersect.unwrap(); 907 if unlikely(intersect == guard.region) { 908 // 如果当前VMA完全包含region,则直接返回当前VMA 909 return Some((None, guard.self_ref.upgrade().unwrap(), None)); 910 } 911 } 912 913 let before: Option<Arc<LockedVMA>> = guard.region.before(®ion).map(|virt_region| { 914 let mut vma: VMA = unsafe { guard.clone() }; 915 vma.region = virt_region; 916 917 let vma: Arc<LockedVMA> = LockedVMA::new(vma); 918 vma 919 }); 920 921 let after: Option<Arc<LockedVMA>> = guard.region.after(®ion).map(|virt_region| { 922 let mut vma: VMA = unsafe { guard.clone() }; 923 vma.region = virt_region; 924 925 let vma: Arc<LockedVMA> = LockedVMA::new(vma); 926 vma 927 }); 928 929 guard.region = region; 930 931 // TODO: 重新设置before、after这两个VMA里面的物理页的anon_vma 932 933 return Some((before, guard.self_ref.upgrade().unwrap(), after)); 934 } 935 } 936 937 /// @brief 虚拟内存区域 938 #[derive(Debug)] 939 pub struct VMA { 940 /// 虚拟内存区域对应的虚拟地址范围 941 region: VirtRegion, 942 /// VMA内的页帧的标志 943 flags: PageFlags<MMArch>, 944 /// VMA内的页帧是否已经映射到页表 945 mapped: bool, 946 /// VMA所属的用户地址空间 947 user_address_space: Option<Weak<AddressSpace>>, 948 self_ref: Weak<LockedVMA>, 949 950 provider: Provider, 951 } 952 953 impl core::hash::Hash for VMA { 954 fn hash<H: Hasher>(&self, state: &mut H) { 955 self.region.hash(state); 956 self.flags.hash(state); 957 self.mapped.hash(state); 958 } 959 } 960 961 /// 描述不同类型的内存提供者或资源 962 #[derive(Debug)] 963 pub enum Provider { 964 Allocated, // TODO:其他 965 } 966 967 #[allow(dead_code)] 968 impl VMA { 969 pub fn region(&self) -> &VirtRegion { 970 return &self.region; 971 } 972 973 /// # 拷贝当前VMA的内容 974 /// 975 /// ### 安全性 976 /// 977 /// 由于这样操作可能由于错误的拷贝,导致内存泄露、内存重复释放等问题,所以需要小心使用。 978 pub unsafe fn clone(&self) -> Self { 979 return Self { 980 region: self.region, 981 flags: self.flags, 982 mapped: self.mapped, 983 user_address_space: self.user_address_space.clone(), 984 self_ref: self.self_ref.clone(), 985 provider: Provider::Allocated, 986 }; 987 } 988 989 #[inline(always)] 990 pub fn flags(&self) -> PageFlags<MMArch> { 991 return self.flags; 992 } 993 994 pub fn pages(&self) -> VirtPageFrameIter { 995 return VirtPageFrameIter::new( 996 VirtPageFrame::new(self.region.start()), 997 VirtPageFrame::new(self.region.end()), 998 ); 999 } 1000 1001 pub fn remap( 1002 &mut self, 1003 flags: PageFlags<MMArch>, 1004 mapper: &mut PageMapper, 1005 mut flusher: impl Flusher<MMArch>, 1006 ) -> Result<(), SystemError> { 1007 assert!(self.mapped); 1008 for page in self.region.pages() { 1009 // kdebug!("remap page {:?}", page.virt_address()); 1010 // 暂时要求所有的页帧都已经映射到页表 1011 // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了 1012 let r = unsafe { 1013 mapper 1014 .remap(page.virt_address(), flags) 1015 .expect("Failed to remap, beacuse of some page is not mapped") 1016 }; 1017 // kdebug!("consume page {:?}", page.virt_address()); 1018 flusher.consume(r); 1019 // kdebug!("remap page {:?} done", page.virt_address()); 1020 } 1021 self.flags = flags; 1022 return Ok(()); 1023 } 1024 1025 /// 检查当前VMA是否可以拥有指定的标志位 1026 /// 1027 /// ## 参数 1028 /// 1029 /// - `prot_flags` 要检查的标志位 1030 pub fn can_have_flags(&self, prot_flags: ProtFlags) -> bool { 1031 let is_downgrade = (self.flags.has_write() || !prot_flags.contains(ProtFlags::PROT_WRITE)) 1032 && (self.flags.has_execute() || !prot_flags.contains(ProtFlags::PROT_EXEC)); 1033 1034 match self.provider { 1035 Provider::Allocated { .. } => true, 1036 1037 #[allow(unreachable_patterns)] 1038 _ => is_downgrade, 1039 } 1040 } 1041 1042 /// 把物理地址映射到虚拟地址 1043 /// 1044 /// @param phys 要映射的物理地址 1045 /// @param destination 要映射到的虚拟地址 1046 /// @param count 要映射的页帧数量 1047 /// @param flags 页面标志位 1048 /// @param mapper 页表映射器 1049 /// @param flusher 页表项刷新器 1050 /// 1051 /// @return 返回映射后的虚拟内存区域 1052 pub fn physmap( 1053 phys: PhysPageFrame, 1054 destination: VirtPageFrame, 1055 count: PageFrameCount, 1056 flags: PageFlags<MMArch>, 1057 mapper: &mut PageMapper, 1058 mut flusher: impl Flusher<MMArch>, 1059 ) -> Result<Arc<LockedVMA>, SystemError> { 1060 { 1061 let mut cur_phy = phys; 1062 let mut cur_dest = destination; 1063 1064 for _ in 0..count.data() { 1065 // 将物理页帧映射到虚拟页帧 1066 let r = unsafe { 1067 mapper.map_phys(cur_dest.virt_address(), cur_phy.phys_address(), flags) 1068 } 1069 .expect("Failed to map phys, may be OOM error"); 1070 1071 // todo: 增加OOM处理 1072 1073 // todo: 将VMA加入到anon_vma中 1074 1075 // 刷新TLB 1076 flusher.consume(r); 1077 1078 cur_phy = cur_phy.next(); 1079 cur_dest = cur_dest.next(); 1080 } 1081 } 1082 1083 let r: Arc<LockedVMA> = LockedVMA::new(VMA { 1084 region: VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE), 1085 flags, 1086 mapped: true, 1087 user_address_space: None, 1088 self_ref: Weak::default(), 1089 provider: Provider::Allocated, 1090 }); 1091 return Ok(r); 1092 } 1093 1094 /// 从页分配器中分配一些物理页,并把它们映射到指定的虚拟地址,然后创建VMA 1095 /// 1096 /// @param destination 要映射到的虚拟地址 1097 /// @param count 要映射的页帧数量 1098 /// @param flags 页面标志位 1099 /// @param mapper 页表映射器 1100 /// @param flusher 页表项刷新器 1101 /// 1102 /// @return 返回映射后的虚拟内存区域 1103 pub fn zeroed( 1104 destination: VirtPageFrame, 1105 page_count: PageFrameCount, 1106 flags: PageFlags<MMArch>, 1107 mapper: &mut PageMapper, 1108 mut flusher: impl Flusher<MMArch>, 1109 ) -> Result<Arc<LockedVMA>, SystemError> { 1110 let mut cur_dest: VirtPageFrame = destination; 1111 // kdebug!( 1112 // "VMA::zeroed: page_count = {:?}, destination={destination:?}", 1113 // page_count 1114 // ); 1115 for _ in 0..page_count.data() { 1116 // kdebug!( 1117 // "VMA::zeroed: cur_dest={cur_dest:?}, vaddr = {:?}", 1118 // cur_dest.virt_address() 1119 // ); 1120 let r = unsafe { mapper.map(cur_dest.virt_address(), flags) } 1121 .expect("Failed to map zero, may be OOM error"); 1122 // todo: 将VMA加入到anon_vma中 1123 // todo: 增加OOM处理 1124 1125 // 稍后再刷新TLB,这里取消刷新 1126 flusher.consume(r); 1127 cur_dest = cur_dest.next(); 1128 } 1129 let r = LockedVMA::new(VMA { 1130 region: VirtRegion::new( 1131 destination.virt_address(), 1132 page_count.data() * MMArch::PAGE_SIZE, 1133 ), 1134 flags, 1135 mapped: true, 1136 user_address_space: None, 1137 self_ref: Weak::default(), 1138 provider: Provider::Allocated, 1139 }); 1140 drop(flusher); 1141 // kdebug!("VMA::zeroed: flusher dropped"); 1142 1143 // 清空这些内存 1144 let virt_iter: VirtPageFrameIter = 1145 VirtPageFrameIter::new(destination, destination.add(page_count)); 1146 for frame in virt_iter { 1147 let paddr = mapper.translate(frame.virt_address()).unwrap().0; 1148 1149 unsafe { 1150 let vaddr = MMArch::phys_2_virt(paddr).unwrap(); 1151 MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE); 1152 } 1153 } 1154 // kdebug!("VMA::zeroed: done"); 1155 return Ok(r); 1156 } 1157 } 1158 1159 impl Drop for VMA { 1160 fn drop(&mut self) { 1161 // 当VMA被释放时,需要确保它已经被从页表中解除映射 1162 assert!(!self.mapped, "VMA is still mapped"); 1163 } 1164 } 1165 1166 impl PartialEq for VMA { 1167 fn eq(&self, other: &Self) -> bool { 1168 return self.region == other.region; 1169 } 1170 } 1171 1172 impl Eq for VMA {} 1173 1174 impl PartialOrd for VMA { 1175 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { 1176 return self.region.partial_cmp(&other.region); 1177 } 1178 } 1179 1180 impl Ord for VMA { 1181 fn cmp(&self, other: &Self) -> cmp::Ordering { 1182 return self.region.cmp(&other.region); 1183 } 1184 } 1185 1186 #[derive(Debug)] 1187 pub struct UserStack { 1188 // 栈底地址 1189 stack_bottom: VirtAddr, 1190 // 当前已映射的大小 1191 mapped_size: usize, 1192 /// 栈顶地址(这个值需要仔细确定!因为它可能不会实时与用户栈的真实栈顶保持一致!要小心!) 1193 current_sp: VirtAddr, 1194 } 1195 1196 impl UserStack { 1197 /// 默认的用户栈底地址 1198 pub const DEFAULT_USER_STACK_BOTTOM: VirtAddr = MMArch::USER_STACK_START; 1199 /// 默认的用户栈大小为8MB 1200 pub const DEFAULT_USER_STACK_SIZE: usize = 8 * 1024 * 1024; 1201 /// 用户栈的保护页数量 1202 pub const GUARD_PAGES_NUM: usize = 4; 1203 1204 /// 创建一个用户栈 1205 pub fn new( 1206 vm: &mut InnerAddressSpace, 1207 stack_bottom: Option<VirtAddr>, 1208 stack_size: usize, 1209 ) -> Result<Self, SystemError> { 1210 let stack_bottom = stack_bottom.unwrap_or(Self::DEFAULT_USER_STACK_BOTTOM); 1211 assert!(stack_bottom.check_aligned(MMArch::PAGE_SIZE)); 1212 1213 // 分配用户栈的保护页 1214 let guard_size = Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE; 1215 let actual_stack_bottom = stack_bottom - guard_size; 1216 1217 let mut prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE; 1218 let map_flags = 1219 MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE; 1220 // kdebug!( 1221 // "map anonymous stack: {:?} {}", 1222 // actual_stack_bottom, 1223 // guard_size 1224 // ); 1225 vm.map_anonymous( 1226 actual_stack_bottom, 1227 guard_size, 1228 prot_flags, 1229 map_flags, 1230 false, 1231 )?; 1232 // test_buddy(); 1233 // 设置保护页只读 1234 prot_flags.remove(ProtFlags::PROT_WRITE); 1235 // kdebug!( 1236 // "to mprotect stack guard pages: {:?} {}", 1237 // actual_stack_bottom, 1238 // guard_size 1239 // ); 1240 vm.mprotect( 1241 VirtPageFrame::new(actual_stack_bottom), 1242 PageFrameCount::new(Self::GUARD_PAGES_NUM), 1243 prot_flags, 1244 )?; 1245 1246 // kdebug!( 1247 // "mprotect stack guard pages done: {:?} {}", 1248 // actual_stack_bottom, 1249 // guard_size 1250 // ); 1251 1252 let mut user_stack = UserStack { 1253 stack_bottom: actual_stack_bottom, 1254 mapped_size: guard_size, 1255 current_sp: actual_stack_bottom - guard_size, 1256 }; 1257 1258 // kdebug!("extend user stack: {:?} {}", stack_bottom, stack_size); 1259 // 分配用户栈 1260 user_stack.initial_extend(vm, stack_size)?; 1261 // kdebug!("user stack created: {:?} {}", stack_bottom, stack_size); 1262 return Ok(user_stack); 1263 } 1264 1265 fn initial_extend( 1266 &mut self, 1267 vm: &mut InnerAddressSpace, 1268 mut bytes: usize, 1269 ) -> Result<(), SystemError> { 1270 let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 1271 let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS; 1272 1273 bytes = page_align_up(bytes); 1274 self.mapped_size += bytes; 1275 1276 vm.map_anonymous( 1277 self.stack_bottom - self.mapped_size, 1278 bytes, 1279 prot_flags, 1280 map_flags, 1281 false, 1282 )?; 1283 1284 return Ok(()); 1285 } 1286 1287 /// 扩展用户栈 1288 /// 1289 /// ## 参数 1290 /// 1291 /// - `vm` 用户地址空间结构体 1292 /// - `bytes` 要扩展的字节数 1293 /// 1294 /// ## 返回值 1295 /// 1296 /// - **Ok(())** 扩展成功 1297 /// - **Err(SystemError)** 扩展失败 1298 #[allow(dead_code)] 1299 pub fn extend( 1300 &mut self, 1301 vm: &mut RwLockWriteGuard<InnerAddressSpace>, 1302 mut bytes: usize, 1303 ) -> Result<(), SystemError> { 1304 let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 1305 let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS; 1306 1307 bytes = page_align_up(bytes); 1308 self.mapped_size += bytes; 1309 1310 vm.map_anonymous( 1311 self.stack_bottom - self.mapped_size, 1312 bytes, 1313 prot_flags, 1314 map_flags, 1315 false, 1316 )?; 1317 1318 return Ok(()); 1319 } 1320 1321 /// 获取栈顶地址 1322 /// 1323 /// 请注意,如果用户栈的栈顶地址发生变化,这个值可能不会实时更新! 1324 pub fn sp(&self) -> VirtAddr { 1325 return self.current_sp; 1326 } 1327 1328 pub unsafe fn set_sp(&mut self, sp: VirtAddr) { 1329 self.current_sp = sp; 1330 } 1331 1332 /// 仅仅克隆用户栈的信息,不会克隆用户栈的内容/映射 1333 pub unsafe fn clone_info_only(&self) -> Self { 1334 return Self { 1335 stack_bottom: self.stack_bottom, 1336 mapped_size: self.mapped_size, 1337 current_sp: self.current_sp, 1338 }; 1339 } 1340 1341 /// 获取当前用户栈的大小(不包括保护页) 1342 pub fn stack_size(&self) -> usize { 1343 return self.mapped_size - Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE; 1344 } 1345 } 1346