5. 用户进程(+ 虚拟内存管理 + 线程管理)

实验要求

  1. 阅读理解文档第八章。
  2. 编程实现:为 rcore 增加 sys_fork 。(20 分)

实验指导

  • 测试文件

  • 测试方法:python3 test.py lab5

  • 参考输出:

    • 该输出仅供参考;
    • 因为调度的不确定性,线程结束的顺序甚至申请到的 TID 会有不同;
    • 故你的输出不需要和该输出完全一样;
    • 在评阅过程中,我们会人工抽查运行结果。
    1. I am child
    2. ret tid is: 0
    3. thread 2 exited, exit code = 0
    4. I am father
    5. ret tid is: 2
    6. thread 1 exited, exit code = 0
    7. I am child
    8. ret tid is: 0
    9. thread 3 exited, exit code = 0
    10. I am father
    11. ret tid is: 3
    12. thread 0 exited, exit code = 0

思考以下问题:

  1. 如何控制子进程的返回值?(线程管理)

    修改上下文中的 a0 寄存器。

  2. 目前尚未实现进程切分,是否可以偷懒把线程当进程用?

    目前,可以。(出于偷懒甚至不需要维护进程的父子关系)

  3. 如何复制一个线程?(虚拟内存管理)

    分配新的栈、新的页表,并将页表的内容进行复制和映射。

  4. 为什么这道题这么难分值还和其它题一样?

    因为有现成的代码可以参考呀(小声)

    GitHub: rcore-os/rCore

一些可能有用的函数实现(仅供参考):

  1. // in syscall.rs
  2. pub const SYS_FORK: usize = 220;
  3. fn sys_fork(tf: &mut TrapFrame) -> isize {
  4. let new_thread = process::current_thread().fork(tf);
  5. let tid = process::add_thread(new_thread);
  6. tid as isize
  7. }
  8. // in paging.rs
  9. impl PageTableImpl {
  10. pub fn get_page_slice_mut<'a>(&mut self, vaddr: usize) -> &'a mut [u8] {
  11. let frame = self
  12. .page_table
  13. .translate_page(Page::of_addr(VirtAddr::new(vaddr)))
  14. .unwrap();
  15. let vaddr = frame.start_address().as_usize() + PHYSICAL_MEMORY_OFFSET;
  16. unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
  17. }
  18. }