XV6 中的 Fork(),子进程是在内核态还是在用户态执行?
Fork() in XV6, does the process child execute in kernel or user mode?
在XV6中,当一个fork()
被调用时,子进程是在内核态还是用户态执行?
这是 XV6 中的分支代码:
// Create a new process copying p as the parent.
// Sets up stack to return as if from system call.
// Caller must set state of returned proc to RUNNABLE.
int fork(void){
int i, pid;
struct proc *np;
struct proc *curproc = myproc();
// Allocate process.
if((np = allocproc()) == 0){
return -1;
}
// Copy process state from proc.
if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){
kfree(np->kstack);
np->kstack = 0;
np->state = UNUSED;
return -1;
}
np->sz = curproc->sz;
np->parent = curproc;
*np->tf = *curproc->tf;
// Clear %eax so that fork returns 0 in the child.
np->tf->eax = 0;
for(i = 0; i < NOFILE; i++)
if(curproc->ofile[i])
np->ofile[i] = filedup(curproc->ofile[i]);
np->cwd = idup(curproc->cwd);
safestrcpy(np->name, curproc->name, sizeof(curproc->name));
pid = np->pid;
acquire(&ptable.lock);
np->state = RUNNABLE;
release(&ptable.lock);
return pid;
}
我做了一些研究,但即使从代码中我也无法理解它是如何工作的。了解它在 UNIX 中的工作原理也会有所帮助
除了eax
寄存器的值和父进程信息外,它几乎是父进程的精确副本,所以它会执行父进程所在的任何上下文。
这里的fork()
函数通过调用allocproc()
创建了一个新的进程结构,并用原进程的值填充它并映射相同的页表。
最后,它将进程状态设置为 RUNNABLE
,这允许调度程序 运行 新进程与父进程一起。
这意味着实际的 运行ning 是由调度程序执行的,而不是此处的 fork 代码。
Sedat 写的完全正确。分叉进程,或者子进程将 运行 在与其父进程相同的上下文中,即内核或用户。
除此之外,我觉得让你感到困惑的是 alloproc()
所做的调用,如 kalloc()
和属性,如 kstack
。这些处理在系统中设置有关页表和内存部分的新进程。
在XV6中,当一个fork()
被调用时,子进程是在内核态还是用户态执行?
这是 XV6 中的分支代码:
// Create a new process copying p as the parent.
// Sets up stack to return as if from system call.
// Caller must set state of returned proc to RUNNABLE.
int fork(void){
int i, pid;
struct proc *np;
struct proc *curproc = myproc();
// Allocate process.
if((np = allocproc()) == 0){
return -1;
}
// Copy process state from proc.
if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){
kfree(np->kstack);
np->kstack = 0;
np->state = UNUSED;
return -1;
}
np->sz = curproc->sz;
np->parent = curproc;
*np->tf = *curproc->tf;
// Clear %eax so that fork returns 0 in the child.
np->tf->eax = 0;
for(i = 0; i < NOFILE; i++)
if(curproc->ofile[i])
np->ofile[i] = filedup(curproc->ofile[i]);
np->cwd = idup(curproc->cwd);
safestrcpy(np->name, curproc->name, sizeof(curproc->name));
pid = np->pid;
acquire(&ptable.lock);
np->state = RUNNABLE;
release(&ptable.lock);
return pid;
}
我做了一些研究,但即使从代码中我也无法理解它是如何工作的。了解它在 UNIX 中的工作原理也会有所帮助
除了eax
寄存器的值和父进程信息外,它几乎是父进程的精确副本,所以它会执行父进程所在的任何上下文。
这里的fork()
函数通过调用allocproc()
创建了一个新的进程结构,并用原进程的值填充它并映射相同的页表。
最后,它将进程状态设置为 RUNNABLE
,这允许调度程序 运行 新进程与父进程一起。
这意味着实际的 运行ning 是由调度程序执行的,而不是此处的 fork 代码。
Sedat 写的完全正确。分叉进程,或者子进程将 运行 在与其父进程相同的上下文中,即内核或用户。
除此之外,我觉得让你感到困惑的是 alloproc()
所做的调用,如 kalloc()
和属性,如 kstack
。这些处理在系统中设置有关页表和内存部分的新进程。