> For the complete documentation index, see [llms.txt](https://nankai.gitbook.io/ucore-os-on-risc-v64/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nankai.gitbook.io/ucore-os-on-risc-v64/lab5/xiang-mu-zu-cheng-yu-zhi-hang-liu.md).

# 项目组成与执行流

## 项目组成

```
lab5
├── Makefile
├── boot
│   ├── asm.h
│   ├── bootasm.S
│   └── bootmain.c
├── kern
│   ├── debug
│   │   ├── assert.h
│   │   ├── kdebug.c
│   │   ├── kdebug.h
│   │   ├── kmonitor.c
│   │   ├── kmonitor.h
│   │   ├── panic.c
│   │   └── stab.h
│   ├── driver
│   │   ├── clock.c
│   │   ├── clock.h
│   │   ├── console.c
│   │   ├── console.h
│   │   ├── ide.c
│   │   ├── ide.h
│   │   ├── intr.c
│   │   ├── intr.h
│   │   ├── kbdreg.h
│   │   ├── picirq.c
│   │   └── picirq.h
│   ├── fs
│   │   ├── fs.h
│   │   ├── swapfs.c
│   │   └── swapfs.h
│   ├── init
│   │   ├── entry.S
│   │   └── init.c
│   ├── libs
│   │   ├── readline.c
│   │   └── stdio.c
│   ├── mm
│   │   ├── default_pmm.c
│   │   ├── default_pmm.h
│   │   ├── kmalloc.c
│   │   ├── kmalloc.h
│   │   ├── memlayout.h
│   │   ├── mmu.h
│   │   ├── pmm.c
│   │   ├── pmm.h
│   │   ├── swap.c
│   │   ├── swap.h
│   │   ├── swap_fifo.c
│   │   ├── swap_fifo.h
│   │   ├── vmm.c
│   │   └── vmm.h
│   ├── process
│   │   ├── entry.S
│   │   ├── proc.c
│   │   ├── proc.h
│   │   └── switch.S
│   ├── schedule
│   │   ├── sched.c
│   │   └── sched.h
│   ├── sync
│   │   └── sync.h
│   ├── syscall
│   │   ├── syscall.c
│   │   └── syscall.h
│   └── trap
│       ├── trap.c
│       ├── trap.h
│       └── trapentry.S
├── lab5.md
├── libs
│   ├── atomic.h
│   ├── defs.h
│   ├── elf.h
│   ├── error.h
│   ├── hash.c
│   ├── list.h
│   ├── printfmt.c
│   ├── rand.c
│   ├── riscv.h
│   ├── sbi.h
│   ├── stdarg.h
│   ├── stdio.h
│   ├── stdlib.h
│   ├── string.c
│   ├── string.h
│   └── unistd.h
├── tools
│   ├── boot.ld
│   ├── function.mk
│   ├── gdbinit
│   ├── grade.sh
│   ├── kernel.ld
│   ├── sign.c
│   ├── user.ld
│   └── vector.c
└── user
    ├── badarg.c
    ├── badsegment.c
    ├── divzero.c
    ├── exit.c
    ├── faultread.c
    ├── faultreadkernel.c
    ├── forktest.c
    ├── forktree.c
    ├── hello.c
    ├── libs
    │   ├── initcode.S
    │   ├── panic.c
    │   ├── stdio.c
    │   ├── syscall.c
    │   ├── syscall.h
    │   ├── ulib.c
    │   ├── ulib.h
    │   └── umain.c
    ├── pgdir.c
    ├── softint.c
    ├── spin.c
    ├── testbss.c
    ├── waitkill.c
    └── yield.c

17 directories, 103 files
```

## 用户进程内存管理

`kern/mm/pmm.[ch]`：添加了用于进程退出（`do_exit`）的内存资源回收的`page_remove_pte`、`unmap_range`、`exit_range`函数和用于创建子进程（`do_fork`）中拷贝父进程内存空间的`copy_range`函数，修改了`pgdir_alloc_page`函数

`kern/mm/vmm.[ch]`：修改：扩展了`mm_struct`数据结构，增加了一系列函数

* `mm_map`/`dup_mmap`/`exit_mmap`：设定/取消/复制/删除用户进程的合法内存空间
* `copy_from_user`/`copy_to_user`：用户内存空间内容与内核内存空间内容的相互拷贝的实现
* `user_mem_check`：搜索vma链表，检查是否是一个合法的用户空间范围

## 用户进程管理

`kern/process/proc.[ch]`：扩展了`proc_struct`数据结构。增加或修改了一系列函数

* `setup_pgdir/put_pgdir`：创建并设置/释放页目录表
* `copy_mm`：复制用户进程的内存空间和设置相关内存管理（如页表等）信息
* `do_exit`：释放进程自身所占内存空间和相关内存管理（如页表等）信息所占空间，唤醒父进程，好让父进程收了自己，让调度器切换到其他进程
* `load_icode`：被`do_execve`调用，完成加载放在内存中的执行程序到进程空间，这涉及到对页表等的修改，分配用户栈
* `do_execve`：先回收自身所占用户空间，然后调用`load_icode`，用新的程序覆盖内存空间，形成一个执行新程序的新进程
* `do_yield`：让调度器执行一次选择新进程的过程
* `do_wait`：父进程等待子进程，并在得到子进程的退出消息后，彻底回收子进程所占的资源（比如子进程的内核栈和进程控制块）
* `do_kill`：给一个进程设置`PF_EXITING`标志（“kill”信息，即要它死掉），这样在trap函数中，将根据此标志，让进程退出
* `KERNEL_EXECVE/__KERNEL_EXECVE/__KERNEL_EXECVE2`：被user\_main调用，执行一用户进程

## 执行流

结合前面所述自行理解、总结。
