get familiar with new code and babystep in fork

This commit is contained in:
ridethepig 2022-11-22 00:54:03 +08:00
parent a9e2c29c26
commit 52a5d090ea
3 changed files with 40 additions and 8 deletions

View File

@ -1,6 +1,6 @@
{ {
"editor.detectIndentation": false, "editor.detectIndentation": false,
"editor.tabSize": 8, "editor.tabSize": 4,
"editor.insertSpaces": false, "editor.insertSpaces": false,
"files.associations": { "files.associations": {
"*.h": "c", "*.h": "c",

View File

@ -1,7 +1,10 @@
#include <assert.h> #include <assert.h>
#include <x86.h>
#include <errno.h>
#include <kern/fork.h> #include <kern/fork.h>
#include <kern/syscall.h> #include <kern/syscall.h>
#include <kern/trap.h>
ssize_t ssize_t
kern_fork(PROCESS_0 *p_fa) kern_fork(PROCESS_0 *p_fa)
@ -11,17 +14,34 @@ kern_fork(PROCESS_0 *p_fa)
// 这样你在焦虑的同时也在浪费时间,就跟你在实验五中被页表折磨一样 // 这样你在焦虑的同时也在浪费时间,就跟你在实验五中被页表折磨一样
// 人在触碰到未知的时候总是害怕的,这是天性,所以请你先冷静下来 // 人在触碰到未知的时候总是害怕的,这是天性,所以请你先冷静下来
// fork系统调用会一步步引导你写出来不会让你本科造火箭的 // fork系统调用会一步步引导你写出来不会让你本科造火箭的
panic("Unimplement! CALM DOWN!"); // panic("Unimplement! CALM DOWN!");
// 推荐是边写边想,而不是想一车然后写,这样非常容易计划赶不上变化 // 推荐是边写边想,而不是想一车然后写,这样非常容易计划赶不上变化
//? before all, lock father
while (xchg(&p_fa->lock, 1) == 1)
schedule();
// fork的第一步你需要找一个空闲IDLE的进程作为你要fork的子进程 // fork的第一步你需要找一个空闲IDLE的进程作为你要fork的子进程
panic("Unimplement! find a idle process"); PROCESS_0 *p_child = NULL;
int i = 0;
//? maybe cli will be better when preserving a proc resource
DISABLE_INT();
for (i = 1; i < PCB_SIZE; ++ i) {
if (proc_table[i].pcb.statu == IDLE) {
proc_table[i].pcb.statu = INITING;
p_child = &proc_table[i];
break;
}
}
ENABLE_INT();
if (p_child == NULL) {
// NO hell. no free proc_table found.
xchg(&p_fa->lock, 0);
return ENOMEM;
}
// 再之后你需要做的是好好阅读一下pcb的数据结构搞明白结构体中每个成员的语义 // 再之后你需要做的是好好阅读一下pcb的数据结构搞明白结构体中每个成员的语义
// 别光扫一遍,要搞明白这个成员到底在哪里被用到了,具体是怎么用的 // 别光扫一遍,要搞明白这个成员到底在哪里被用到了,具体是怎么用的
// 可能exec和exit系统调用的代码能够帮助你对pcb的理解不先理解好pcb你fork是无从下手的 // 可能exec和exit系统调用的代码能够帮助你对pcb的理解不先理解好pcb你fork是无从下手的
panic("Unimplement! read pcb"); // panic("Unimplement! read pcb");
// 在阅读完pcb之后终于可以开始fork工作了 // 在阅读完pcb之后终于可以开始fork工作了
// 本质上相当于将父进程的pcb内容复制到子进程pcb中 // 本质上相当于将父进程的pcb内容复制到子进程pcb中
@ -33,7 +53,19 @@ kern_fork(PROCESS_0 *p_fa)
// 3. 在fork结束后肯定会调度到子进程那么你怎么保证子进程能够正常进入用户态 // 3. 在fork结束后肯定会调度到子进程那么你怎么保证子进程能够正常进入用户态
// (你肯定会觉得这个问题问的莫名其妙的,只能说你如果遇到那一块问题了就会体会到这个问题的重要性, // (你肯定会觉得这个问题问的莫名其妙的,只能说你如果遇到那一块问题了就会体会到这个问题的重要性,
// 这需要你对调度整个过程都掌握比较清楚) // 这需要你对调度整个过程都掌握比较清楚)
panic("Unimplement! copy pcb?"); //? Start to COPY
//? 1. COPY PCB
*p_child = *p_fa; // anyway, first copy all
p_child->cr3 = 0;
p_child->fork_tree.p_fa = NULL;
p_child->fork_tree.sons = NULL;
p_child->page_list = NULL;
// the null before is just a reminder to change them
p_child->pid = i; // well, for simplicity, let pid be index in proc table
p_child->user_regs.eax = 0; //! maybe, set user_ctx.eax as the retval?
//? 2. ALLOC PAGES AND COPY PHYSICAL MEMORY
//TODO see how to copy the pages from parent
//? 3. SET OTHER CHILD STATUS
// 别忘了维护进程树,将这对父子进程关系添加进去 // 别忘了维护进程树,将这对父子进程关系添加进去
panic("Unimplement! maintain process tree"); panic("Unimplement! maintain process tree");

View File

@ -40,7 +40,7 @@ void kernel_main(void)
p_proc->priority = p_proc->ticks = 1; p_proc->priority = p_proc->ticks = 1;
// 在实现了exec系统调用后main函数的负担就少了 // 在实现了exec系统调用后main函数的负担就少了
// 只需要调用一个函数接口就能实现进程的加载 // 只需要调用一个函数接口就能实现进程的加载
if (do_exec("initproc.bin") < 0) if (do_exec("testfork.bin") < 0)
panic("init process failed"); panic("init process failed");
// 切换tss // 切换tss
tss.esp0 = (u32)(&p_proc->user_regs + 1); tss.esp0 = (u32)(&p_proc->user_regs + 1);