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