diff --git a/课程设计.md b/课程设计.md index aa538d0..a9a08d4 100644 --- a/课程设计.md +++ b/课程设计.md @@ -2,7 +2,10 @@ > 扩充proxy kernel的代码,使你的内核可以支持以下应用程序: -## 应用程序一: ## +## 实验一 多进程支持 ## + +### 应用: ### + App5_1的代码如下: int main(){ @@ -35,14 +38,79 @@ App5_1的代码如下: return 0; } + +### 实验一任务: ### + + +#### 任务一 : proc_pagetable/ vmcopy #### + + 实验任务描述: + +实现pk/proc.c中的proc_pagetable与vmcopy函数,为进程创建用户页表,并映射用户内存,确保你的代码仍可以保证app5的正确运行。 -以上是一段多进程的代码,我们可以结合下图进行分析:
+实验预期输出: -
+ $ spike obj/pke app/elf/app5 +得到输出: + PKE IS RUNNING + to host 10 + from host 0 + elf name app/elf/app5 + sched class: RR_scheduler + ++ setup timer interrupts + log: proc init + father process + this is father process;my pid = 1 + this is child process;my pid = 2 + + +#### 任务二:do_wait #### + + 实验任务描述: +实现`do_wait`函数,支持app5_1.c的运行 + + $ spike obj/pke app/elf/app5_1 +预期得到输出: + + PKE IS RUNNING + to host 10 + from host 0 + elf name app/elf/app5_1 + sched class: RR_scheduler + ++ setup timer interrupts + log: proc init + print proc app5_1 + print proc this is child process;my pid = 2 + print proc a=9 + print proc this is child process;my pid = 3 + print proc a=6 + print proc this is farther process;my pid = 2 + print proc a=5 + print proc this is farther process;my pid = 1 + print proc a=8 + print proc this is child process;my pid = 4 + print proc a=5 + print proc this is farther process;my pid = 1 + +此时运行测试脚本: + + $ python3 ./pke-final-1 + +预期得到输出: + + build pk : OK + running app5_1 : OK + test fork : OK + Score: 20/20 + + +### 实验一提示: ### + +app5_1.c是一段多进程的代码,我们可以结合下图进行分析:
app5_1
@@ -265,25 +333,6 @@ start_user中首先恢复sstatus以及sepc,然后加载32个通用寄存器, - 其四、该虚拟地址对应着用户栈,由于我们在proc_pagetable函数中已近为其分配了内存,此时只需要复制父进程的用户栈。 -### 任务一:proc_pagetable/ vmcopy ### -任务描述:实现pk/proc.c中的proc_pagetable与vmcopy函数,为进程创建用户页表,并映射用户内存,确保你的代码仍可以保证app5的正确运行。 - - $ spike obj/pke app/elf/app5 - -预期得到输出: - - PKE IS RUNNING - to host 10 - from host 0 - elf name app/elf/app5 - sched class: RR_scheduler - ++ setup timer interrupts - log: proc init - father process - this is father process;my pid = 1 - this is child process;my pid = 2 - ----------- 至此,我们进一步完善了对fork的支持。接下来,我们来看进程间的同步。
@@ -369,48 +418,17 @@ Schedule会选取下一个进程,随即进入switch_to,这又是一段汇编 当父进程被唤醒后,进入`wakeup_proc`的代码,在`wakeup_proc`函数中恢复了父进程的运行状态,随即再次调用schedule函数。如上文所述,schedule再次加载父进程的上下文,还记的方才父进程上下文中的ra寄存器的值吗?父进程将根据此值返回schedule中`proc_run`的下一行地址继续上次的代码,并返回schedule的调用函数`do_wai`t。`do_wait`里我们将再次查看子进程的state,若为PROC_ZOMBIE则返回。至此wait系统调用执行完毕。 -### 任务二:do_wait ### -任务描述:实现`do_wait`函数,支持app5_1.c的运行 - $ spike obj/pke app/elf/app5_1 -预期得到输出: +---------- - PKE IS RUNNING - to host 10 - from host 0 - elf name app/elf/app5_1 - sched class: RR_scheduler - ++ setup timer interrupts - log: proc init - print proc app5_1 - print proc this is child process;my pid = 2 - print proc a=9 - print proc this is child process;my pid = 3 - print proc a=6 - print proc this is farther process;my pid = 2 - print proc a=5 - print proc this is farther process;my pid = 1 - print proc a=8 - print proc this is child process;my pid = 4 - print proc a=5 - print proc this is farther process;my pid = 1 -此时运行测试脚本: +## 实验二 信号量 ## - $ python3 ./pke-final-1 - -预期得到输出: - - build pk : OK - running app5_1 : OK - test fork : OK - Score: 20/20 +### 实验二应用输入: ### ----------- -## 应用程序二 ## 到目前为止,我们已近实现了进程间的简单同步。接下来,我们更进一步,考虑信号量的实现。App5_2的代码如下: #include @@ -501,6 +519,30 @@ Schedule会选取下一个进程,随即进入switch_to,这又是一段汇编 上述代码是一个简单的生产者消费者程序,由一个父进程创建两个子进程,父进程作为producer而子进程作为consumer。这里维护了三个信号量,mutex作为互斥信号量,为临界区提供互斥访问,empty用来维护空闲缓冲区,full则用来维护被填充的缓存区。 + +### 实验二任务: ### + +实验二任务描述: + +实现`__down`函数,支持app5_2.c的运行 + +实验二预期输出: + + $ spike obj/pke app/elf/app5_2 +预期得到输出中,父进程生产的数量等于两个子进程消费的数量之和。运行脚本: + + $ python3 ./pke-final-2 +预期得到输出: + + build pk : OK + running app5_2 : OK + test sema : OK + Score: 20/20 + + +### 实验二提示: ### + + 在程序执行的过程中,任务常常会因为某一条件没有达成而进入等待状态,具到的上述的例子,当producer发现没有空闲的缓存区即empty不足时,或者consumer发现full不足时,二者均会进入等待状态。等待条件得到满足,然后继续运行。这种机制,我们可以使用等待队列来实现,等待某一条件的进程在条件未满足时加入到等待队列当中,当条件满足时在遍历对应的队列唤醒进程,并且将进程从队列中删除。 在此,我们定义结构体wait_t如下: @@ -614,22 +656,11 @@ vaddr是信号量在用户空间的地址,即&empty的值。这里我们将信 相应的,在down的代码中需要执行相反的逻辑,首先,需要判断value的值是否大于0,若value值大于0,则可以直接进行减操作。若否则需要将当前进程加入等待队列,并设置其state与wait_state。接着需要调用schedule。当schedule返回时,需要对唤醒标准进行判断,并将进程从等待队列中删除。 -### 任务三:__down ### -任务描述:实先`__down`函数,支持app5_2.c的运行 - - $ spike obj/pke app/elf/app5_2 -预期得到输出中,父进程生产的数量等于两个子进程消费的数量之和。运行脚本: - - $ python3 ./pke-final-2 -预期得到输出: - - build pk : OK - running app5_2 : OK - test sema : OK - Score: 20/20 ---------- +### 提交课设 ### + 至此为止,你已经完成了本实验的所有代码,运行脚本./pke-final: $ python3 ./pke-final