testwait.bin ok
This commit is contained in:
parent
359c4ab5e2
commit
9f77409a4f
@ -125,7 +125,7 @@ kern_fork(PROCESS_0 *p_fa)
|
|||||||
if (proc_child == NULL) {
|
if (proc_child == NULL) {
|
||||||
// NO hell. no free proc_table found.
|
// NO hell. no free proc_table found.
|
||||||
xchg(&p_fa->lock, 0);
|
xchg(&p_fa->lock, 0);
|
||||||
return ENOMEM;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
PROCESS_0 *p_child = &proc_child->pcb;
|
PROCESS_0 *p_child = &proc_child->pcb;
|
||||||
// 再之后你需要做的是好好阅读一下pcb的数据结构,搞明白结构体中每个成员的语义
|
// 再之后你需要做的是好好阅读一下pcb的数据结构,搞明白结构体中每个成员的语义
|
||||||
|
|||||||
@ -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("testfork.bin") < 0)
|
if (do_exec("initproc.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);
|
||||||
|
|||||||
83
kern/wait.c
83
kern/wait.c
@ -1,9 +1,23 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <mmu.h>
|
#include <mmu.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <x86.h>
|
||||||
|
|
||||||
#include <kern/syscall.h>
|
#include <kern/syscall.h>
|
||||||
#include <kern/wait.h>
|
#include <kern/wait.h>
|
||||||
|
#include <kern/process.h>
|
||||||
|
#include <kern/pmap.h>
|
||||||
|
#include <kern/sche.h>
|
||||||
|
#include <kern/kmalloc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
The wait() system call suspends execution of the calling thread
|
||||||
|
until one of its children terminates.
|
||||||
|
RETURN VALUE
|
||||||
|
on success, returns the process ID of the terminated child;
|
||||||
|
on failure, -1 is returned.
|
||||||
|
! however the testwait.bin expects a valued return other than simply -1
|
||||||
|
*/
|
||||||
ssize_t
|
ssize_t
|
||||||
kern_wait(int *wstatus)
|
kern_wait(int *wstatus)
|
||||||
{
|
{
|
||||||
@ -13,21 +27,82 @@ kern_wait(int *wstatus)
|
|||||||
|
|
||||||
// 在实现之前你必须得读一遍文档`man 2 wait`
|
// 在实现之前你必须得读一遍文档`man 2 wait`
|
||||||
// 了解到wait大概要做什么
|
// 了解到wait大概要做什么
|
||||||
panic("Unimplement! Read The F**king Manual");
|
// panic("Unimplement! Read The F**king Manual");
|
||||||
|
|
||||||
// 当然读文档是一方面,最重要的还是代码实现
|
// 当然读文档是一方面,最重要的还是代码实现
|
||||||
// wait系统调用与exit系统调用关系密切,所以在实现wait之前需要先读一遍exit为好
|
// wait系统调用与exit系统调用关系密切,所以在实现wait之前需要先读一遍exit为好
|
||||||
// 可能读完exit的代码你可能知道wait该具体做什么了
|
// 可能读完exit的代码你可能知道wait该具体做什么了
|
||||||
panic("Unimplement! Read The F**king Source Code");
|
// panic("Unimplement! Read The F**king Source Code");
|
||||||
|
|
||||||
|
PROCESS_0 *p_fa = &p_proc_ready->pcb;
|
||||||
|
int child_pid = -1;
|
||||||
|
again:
|
||||||
|
while (xchg(&p_fa->lock, 1) == 1)
|
||||||
|
schedule();
|
||||||
|
struct son_node* p_son = p_fa->fork_tree.sons;
|
||||||
|
if (p_son == NULL) {
|
||||||
|
xchg(&p_fa->lock, 0);
|
||||||
|
return -ECHILD;
|
||||||
|
}
|
||||||
|
assert(p_son->pre == NULL); // make sure it is the head of the list
|
||||||
|
while (p_son != NULL) {
|
||||||
|
if (p_son->p_son->statu == ZOMBIE) {
|
||||||
|
/*
|
||||||
|
struct s_proc {
|
||||||
|
user_regs; // let it be
|
||||||
|
kern_regs; // let it be
|
||||||
|
lock; // get and release before kfree
|
||||||
|
statu; // set to IDLE
|
||||||
|
pid; // keep it util return
|
||||||
|
cr3; // let it be
|
||||||
|
page_list; // recycle it
|
||||||
|
exit_code; // set to wstatus
|
||||||
|
priority; // let it be
|
||||||
|
ticks; // let it be
|
||||||
|
fork_tree; // already cleared
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
while (xchg(&p_son->p_son->lock, 1) == 1)
|
||||||
|
schedule();
|
||||||
|
// just use this value, which is '(status & 0xFF) << 8' in exit.c::do_exit
|
||||||
|
if (wstatus != NULL)
|
||||||
|
*wstatus = p_son->p_son->exit_code;
|
||||||
|
// recycle_pages in pmap.c
|
||||||
|
recycle_pages(p_son->p_son->page_list);
|
||||||
|
// free it in proc table, 'cause in fork I judge free by statu
|
||||||
|
p_son->p_son->statu = IDLE;
|
||||||
|
// remove p_son from p_fa's son list
|
||||||
|
if (p_son->pre != NULL) {
|
||||||
|
p_son->pre->nxt = p_son->nxt;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p_fa->fork_tree.sons = p_son->nxt;
|
||||||
|
}
|
||||||
|
if (p_son->nxt != NULL) {
|
||||||
|
p_son->nxt->pre = p_son->pre;
|
||||||
|
}
|
||||||
|
// keep p_son's pid for retval, 'cause the pointer will get freed before return
|
||||||
|
child_pid = p_son->p_son->pid;
|
||||||
|
xchg(&p_son->p_son->lock, 0);
|
||||||
|
kfree(p_son);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
p_son = p_son->nxt;
|
||||||
|
}
|
||||||
|
p_fa->statu = SLEEP;
|
||||||
|
xchg(&p_fa->lock, 0);
|
||||||
|
schedule();
|
||||||
|
goto again;
|
||||||
// 接下来就是你自己的实现了,我们在设计的时候这段代码不会有太大问题
|
// 接下来就是你自己的实现了,我们在设计的时候这段代码不会有太大问题
|
||||||
// 在实现完后你任然要对自己来个灵魂拷问
|
// 在实现完后你任然要对自己来个灵魂拷问
|
||||||
// 1. 上锁上了吗?所有临界情况都考虑到了吗?(永远要相信有各种奇奇怪怪的并发问题)
|
// 1. 上锁上了吗?所有临界情况都考虑到了吗?(永远要相信有各种奇奇怪怪的并发问题)
|
||||||
// 2. 所有错误情况都判断到了吗?错误情况怎么处理?(RTFM->`man 2 wait`)
|
// 2. 所有错误情况都判断到了吗?错误情况怎么处理?(RTFM->`man 2 wait`)
|
||||||
// 3. 是否所有的资源都正确回收了?
|
// 3. 是否所有的资源都正确回收了?
|
||||||
// 4. 你写的代码真的符合wait语义吗?
|
// 4. 你写的代码真的符合wait语义吗?
|
||||||
panic("Unimplement! soul torture");
|
done:
|
||||||
return 0;
|
xchg(&p_fa->lock, 0);
|
||||||
|
// panic("Unimplement! soul torture");
|
||||||
|
return child_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user