diff --git a/doc/memory.md b/doc/内核原理-内存管理.md
similarity index 100%
rename from doc/memory.md
rename to doc/内核原理-内存管理.md
diff --git a/doc/内核原理-系统调用.md b/doc/内核原理-系统调用.md
new file mode 100644
index 0000000..4ce99e0
--- /dev/null
+++ b/doc/内核原理-系统调用.md
@@ -0,0 +1,39 @@
+# System Call
+System Call即系统调用(以下简称syscall),用于在用户程序中执行一些特权模式下才能完成的操作(如I/O操作)。
+对于处理器而言,syscall是一种同步发生的事件,在基于RISC-V的操作系统中由`ecall`指令(Environment Call)产生。
+当系统调用事件结束后,处理器将返回到ecall指令的下一条指令继续执行。
+
+原版xv6的文档将“system call”、“exception”和“(device) interrupt”统称为“trap”。
+在RISC-V指令集手册的1.6节中,对“exception”、“interrupt”和“trap”的定义是这样的:
+
+> We use the term *exception* to refer to an unusual condition occurring at run time associated with
+an instruction in the current RISC-V hart. We use the term *interrupt* to refer to an external
+asynchronous event that may cause a RISC-V hart to experience an unexpected transfer of control.
+We use the term *trap* to refer to the transfer of control to a trap handler caused by either an
+exception or an interrupt.
+
+从这个角度来看,trap在RISC-V的语境下指的是控制权的转换,也就是特权级的转换。这可能与我们平常使用的术语有一定出入,需要注意。
+
+## 在RISC-V中请求系统调用
+在RISC-V的用户程序中,使用`ecall`指令请求syscall。操作系统提供不同功能的syscall,对应不同的请求调用号。
+因此请求前,需要向`a7`寄存器中写入所请求的syscall的调用号。以下为一个请求8号调用的例子:
+
+```
+li a7, 8
+ecall
+```
+
+## 系统调用的处理过程
+Syscall涉及到特权态的转换,需要经过trap过程。对于用户程序而言,一般是从用户模式(U模式)陷入到监管模式(S模式)。
+我们知道,操作系统中有中断向量表,保存着处理各类中断的中断例程的入口,syscall的中断处理例程自然也在其中。
+而对于不同类型的调用请求,syscall的处理例程也有相应的系统调用表,保存不同类型的系统调用功能函数的入口。
+根据用户事先写入寄存器的系统调用号,syscall的处理例程调用相应的功能函数,完成系统调用,随后返回至原先的特权态。
+
+
+
+
+# 参考文档
+
++ [*xv6: a simple, Unix-like teaching operating system*](https://pdos.csail.mit.edu/6.S081/2020/xv6/book-riscv-rev1.pdf)
++ [*The RISC-V Instruction Set Manual Volume I: Unprivileged ISA*](https://github.com/riscv/riscv-isa-manual/releases/download/draft-20210212-c879d5a/riscv-spec.pdf)
++ [《RISC-V手册——一本开源指令集的指南》](http://riscvbook.com/chinese/RISC-V-Reader-Chinese-v2p1.pdf)
\ No newline at end of file
diff --git a/doc/内核原理-进程管理.md b/doc/内核原理-进程管理.md
new file mode 100644
index 0000000..225936d
--- /dev/null
+++ b/doc/内核原理-进程管理.md
@@ -0,0 +1,8 @@
+# 进程管理
+
+## 自旋锁
+讨论进程管理,就必须先搞懂自旋锁。
+
+1. 为了避免死锁,加锁和释放锁中涉及开关中断,为了保证释放锁之后与加锁之前的中断使能标志保持一致,需要保存加锁之前关中断时的中断使能状态,在释放锁之后开中断时将中断使能恢复到之前所保存的状态。(即封装之后的push_off()和pop_off())
+2. 由于现代编译器的代码优化和指令重排以及现代CPU的乱序执行(Out-of-Order Execution),在上锁期间需要额外的操作来保证读写操作的顺序一致性,在RISC-V中可以用__sync_synchronize指令来保证严格的执行顺序。(注:关于这个问题可以具体参考[这篇文章](https://www.0xffffff.org/2017/02/21/40-atomic-variable-mutex-and-memory-barrier/))
+
diff --git a/doc/sdcard.md b/doc/构建调试-SD卡驱动.md
similarity index 100%
rename from doc/sdcard.md
rename to doc/构建调试-SD卡驱动.md
diff --git a/doc/s_extern_interrupt.md b/doc/构建调试-S态外部中断.md
similarity index 100%
rename from doc/s_extern_interrupt.md
rename to doc/构建调试-S态外部中断.md
diff --git a/doc/boot.md b/doc/构建调试-开机启动.md
similarity index 100%
rename from doc/boot.md
rename to doc/构建调试-开机启动.md
diff --git a/doc/fs.md b/doc/构建调试-文件系统.md
similarity index 100%
rename from doc/fs.md
rename to doc/构建调试-文件系统.md
diff --git a/doc/timer.md b/doc/构建调试-时钟中断.md
similarity index 100%
rename from doc/timer.md
rename to doc/构建调试-时钟中断.md
diff --git a/doc/syscall.md b/doc/构建调试-系统调用.md
similarity index 58%
rename from doc/syscall.md
rename to doc/构建调试-系统调用.md
index e2a9dd7..ff81e47 100644
--- a/doc/syscall.md
+++ b/doc/构建调试-系统调用.md
@@ -1,43 +1,3 @@
-+ [System Call的执行](#Syscall在xv6-k210中的实现与执行)
-+ [System Call的添加](#如何在xv6-k210中添加syscall)
-
-
-
-
-# System Call
-System Call即系统调用(以下简称syscall),用于在用户程序中执行一些特权模式下才能完成的操作(如I/O操作)。
-对于处理器而言,syscall是一种同步发生的事件,在基于RISC-V的操作系统中由`ecall`指令(Environment Call)产生。
-当系统调用事件结束后,处理器将返回到ecall指令的下一条指令继续执行。
-
-原版xv6的文档将“system call”、“exception”和“(device) interrupt”统称为“trap”。
-在RISC-V指令集手册的1.6节中,对“exception”、“interrupt”和“trap”的定义是这样的:
-
-> We use the term *exception* to refer to an unusual condition occurring at run time associated with
-an instruction in the current RISC-V hart. We use the term *interrupt* to refer to an external
-asynchronous event that may cause a RISC-V hart to experience an unexpected transfer of control.
-We use the term *trap* to refer to the transfer of control to a trap handler caused by either an
-exception or an interrupt.
-
-从这个角度来看,trap在RISC-V的语境下指的是控制权的转换,也就是特权级的转换。这可能与我们平常使用的术语有一定出入,需要注意。
-
-## 在RISC-V中请求系统调用
-在RISC-V的用户程序中,使用`ecall`指令请求syscall。操作系统提供不同功能的syscall,对应不同的请求调用号。
-因此请求前,需要向`a7`寄存器中写入所请求的syscall的调用号。以下为一个请求8号调用的例子:
-
-```
-li a7, 8
-ecall
-```
-
-## 系统调用的处理过程
-Syscall涉及到特权态的转换,需要经过trap过程。对于用户程序而言,一般是从用户模式(U模式)陷入到监管模式(S模式)。
-我们知道,操作系统中有中断向量表,保存着处理各类中断的中断例程的入口,syscall的中断处理例程自然也在其中。
-而对于不同类型的调用请求,syscall的处理例程也有相应的系统调用表,保存不同类型的系统调用功能函数的入口。
-根据用户事先写入寄存器的系统调用号,syscall的处理例程调用相应的功能函数,完成系统调用,随后返回至原先的特权态。
-
-
-
-
# Syscall在xv6-k210中的实现与执行
Syscall是如何实现与执行的呢?以下从用户程序出发,分析在xv6-k210中系统调用的过程。
@@ -202,101 +162,3 @@ static uint64 (*syscalls[])(void) = {
-
-# 如何在xv6-k210中添加syscall
-
-了解了Syscall在xv6-k210中的执行过程,为系统添加一个新的syscall功能就不是什么难事了。添加新系统调用的步骤如下:
-
-1. 在xv6-uesr目录下
- + 在uesr.h文件中,添加新系统调用封装后的函数声明,假设其函数名为`mysyscall`。
- + 在usys.pl文件末尾,添加如下行:
-
- ```perl
- ......
- entry("mysyscall");
- ```
-
-2. 在kernel目录下
- + 在include/syscall.h文件中,添加新系统调用号的宏定义:
-
- ```C
- ......
- #define SYS_mysyscall ?
- ```
-
- 其中,“?”为新的合法系统调用号,本质上是一个数组下标,可根据需要设置,建议按顺序递增添加。
-
- + 在syscall.c文件中,添加功能函数的声明,并更新系统调用表:
-
- ```C
- ......
- extern uint64 sys_mysyscall(void);
-
- static uint64 (*syscalls[])(void) = {
- ......
- [SYS_mysyscall] sys_mysyscall,
- };
-
- ```
-3. 根据该系统调用的功能,选择一个适合的内核模块的源文件,在其中实现`sys_mysyscall`函数的功能。
- 例如,与文件相关的系统调用可以在kernel/sysfile.c中添加。
- 可以利用syscall.c文件中提供的相关函数,在`sys_mysyscall`中获取用户进程传递的参数。
-
-下面给出一个更具体的例子。在我们的移植工作中,我们需要测试用户进程的运行,使其向屏幕进行输出。
-但当时用户态尚未支持`printf`函数,我们便通过系统调用,在S态进行一些输出。为此,我们需要添加一个`test_proc`函数。
-
-首先,我们在xv6-uesr/uesr.h文件中添加函数声明,为用户程序添加调用接口:
-```C
-int test_proc(void);
-```
-在xv6-uesr/usys.pl中添加行:
-```perl
-entry("test_proc");
-```
-随后修改内核,在kernel/include/syscall.h中添加调用号,调用号可以自行选择,这里我们选择22,表示第22个系统调用。
-```C
-#define SYS_test_proc 22
-```
-最后,在kernel/include/syscall.c中修改系统调用表,以及添加函数`sys_test_proc`:
-```C
-extern uint64 sys_test_proc(void);
-
-static uint64 (*syscalls[])(void) = {
- ......
- [SYS_test_proc] sys_test_proc,
-};
-
-uint64 sys_test_proc(void) {
- printf("hello world from proc %d, hart %d\n", myproc()->pid, r_tp());
- return 0;
-}
-```
-至此,我们就已经成功添加了一个系统调用。在用户程序中可以使用这个系统调用,例如以下的用户程序实例:
-```C
-#include "kernel/include/types.h"
-#include "kernel/include/stat.h"
-#include "xv6-user/user.h"
-
-int main()
-{
- int n = 10;
- while (n--) {
- test_proc();
- }
- exit(0);
-}
-```
-编译运行后的结果如下图所示(编译用户程序的方法详见[此处](./fs.md)):
-
-![](/img/syscall_test.png)
-
-
-
-
-
-# 参考文档
-
-+ [*xv6: a simple, Unix-like teaching operating system*](https://pdos.csail.mit.edu/6.S081/2020/xv6/book-riscv-rev1.pdf)
-+ [*The RISC-V Instruction Set Manual Volume I: Unprivileged ISA*](https://github.com/riscv/riscv-isa-manual/releases/download/draft-20210212-c879d5a/riscv-spec.pdf)
-+ [《RISC-V手册——一本开源指令集的指南》](http://riscvbook.com/chinese/RISC-V-Reader-Chinese-v2p1.pdf)
-
diff --git a/doc/proc.md b/doc/构建调试-进程管理.md
similarity index 100%
rename from doc/proc.md
rename to doc/构建调试-进程管理.md
diff --git a/doc/memory-code.md b/doc/用户使用-内存管理.md
similarity index 100%
rename from doc/memory-code.md
rename to doc/用户使用-内存管理.md
diff --git a/doc/用户使用-系统调用.md b/doc/用户使用-系统调用.md
new file mode 100644
index 0000000..0307e0c
--- /dev/null
+++ b/doc/用户使用-系统调用.md
@@ -0,0 +1,90 @@
+# 如何在xv6-k210中添加syscall
+
+了解了Syscall在xv6-k210中的执行过程,为系统添加一个新的syscall功能就不是什么难事了。添加新系统调用的步骤如下:
+
+1. 在xv6-uesr目录下
+ + 在uesr.h文件中,添加新系统调用封装后的函数声明,假设其函数名为`mysyscall`。
+ + 在usys.pl文件末尾,添加如下行:
+
+ ```perl
+ ......
+ entry("mysyscall");
+ ```
+
+2. 在kernel目录下
+ + 在include/syscall.h文件中,添加新系统调用号的宏定义:
+
+ ```C
+ ......
+ #define SYS_mysyscall ?
+ ```
+
+ 其中,“?”为新的合法系统调用号,本质上是一个数组下标,可根据需要设置,建议按顺序递增添加。
+
+ + 在syscall.c文件中,添加功能函数的声明,并更新系统调用表:
+
+ ```C
+ ......
+ extern uint64 sys_mysyscall(void);
+
+ static uint64 (*syscalls[])(void) = {
+ ......
+ [SYS_mysyscall] sys_mysyscall,
+ };
+
+ ```
+3. 根据该系统调用的功能,选择一个适合的内核模块的源文件,在其中实现`sys_mysyscall`函数的功能。
+ 例如,与文件相关的系统调用可以在kernel/sysfile.c中添加。
+ 可以利用syscall.c文件中提供的相关函数,在`sys_mysyscall`中获取用户进程传递的参数。
+
+下面给出一个更具体的例子。在我们的移植工作中,我们需要测试用户进程的运行,使其向屏幕进行输出。
+但当时用户态尚未支持`printf`函数,我们便通过系统调用,在S态进行一些输出。为此,我们需要添加一个`test_proc`函数。
+
+首先,我们在xv6-uesr/uesr.h文件中添加函数声明,为用户程序添加调用接口:
+```C
+int test_proc(void);
+```
+在xv6-uesr/usys.pl中添加行:
+```perl
+entry("test_proc");
+```
+随后修改内核,在kernel/include/syscall.h中添加调用号,调用号可以自行选择,这里我们选择22,表示第22个系统调用。
+```C
+#define SYS_test_proc 22
+```
+最后,在kernel/include/syscall.c中修改系统调用表,以及添加函数`sys_test_proc`:
+```C
+extern uint64 sys_test_proc(void);
+
+static uint64 (*syscalls[])(void) = {
+ ......
+ [SYS_test_proc] sys_test_proc,
+};
+
+uint64 sys_test_proc(void) {
+ printf("hello world from proc %d, hart %d\n", myproc()->pid, r_tp());
+ return 0;
+}
+```
+至此,我们就已经成功添加了一个系统调用。在用户程序中可以使用这个系统调用,例如以下的用户程序实例:
+```C
+#include "kernel/include/types.h"
+#include "kernel/include/stat.h"
+#include "xv6-user/user.h"
+
+int main()
+{
+ int n = 10;
+ while (n--) {
+ test_proc();
+ }
+ exit(0);
+}
+```
+编译运行后的结果如下图所示(编译用户程序的方法详见[此处](./fs.md)):
+
+![](/img/syscall_test.png)
+
+
+
+
diff --git a/kernel/kalloc.c b/kernel/kalloc.c
index 1c9e958..5d2c1c2 100644
--- a/kernel/kalloc.c
+++ b/kernel/kalloc.c
@@ -13,7 +13,6 @@
void freerange(void *pa_start, void *pa_end);
extern char kernel_end[]; // first address after kernel.
- // defined by k210.ld.
struct run {
struct run *next;