forked from vivekp/minix-1
-
Notifications
You must be signed in to change notification settings - Fork 7
exit()
bluaxe edited this page May 31, 2013
·
10 revisions
用户进程通过syscall
向PM发送exit
请求.
PM收到exit
消息后调用do_exit()
,再调用exit_proc()
exit_proc()
做了以下的事情:
1. 通过进程mproc表查找进程的slot number, endpoint与procgrp.
proc_nr = (int) (rmp - mproc);
proc_nr_e = rmp->mp_endpoint;
procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
2. 在进程mproc表中检查是否有计时器,如果有的话清零.
if (rmp->mp_flags & ALARM_ON) set_alarm(rmp, (clock_t) 0);
3. 将自己进程是用户态时间与系统态时间加到父进程上。
p_mp->mp_child_utime += user_time + rmp->mp_child_utime; /* add user time */
p_mp->mp_child_stime += sys_time + rmp->mp_child_stime; /* add system time */
4. 通过`sys_stop`进行内核调用,在`do_runctl`中将进程的proc表中标记位标记为`RTS_PROC_STOP`;
if ((r = sys_stop(proc_nr_e)) != OK) /* stop the process */
panic("sys_stop failed: %d", r);
-> #define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, 0)
5. 通过`vm_willexit`在vm服务器中将`vmflag`置为`VMF_EXITING`;
6. 通过`tell_VFS`向vfs服务器发送异步请求(asynsend),关闭此进程打开文件标识符等等操作,完成后向pm发送完成消息.
7. 在进程mproc表标记位中清除`IN_USE|VFS_CALL|PRIV_PROC|TRACE_EXIT`等状态位,并标记为`EXITING`.
rmp->mp_flags &= (IN_USE|VFS_CALL|PRIV_PROC|TRACE_EXIT);
rmp->mp_flags |= EXITING;
8. 如果是系统进程就通过内核执行sys_clear,清除内核proc结构
if (rmp->mp_flags & PRIV_PROC){
if((r= sys_clear(rmp->mp_endpoint)) != OK)
panic("exit_proc: sys_clear failed: %d", r);
}
8. 通过`zombify`函数 , 通知`tracer`停止
if (rmp->mp_tracer != NO_TRACER && rmp->mp_tracer != rmp->mp_parent) {
rmp->mp_flags |= TRACE_ZOMBIE;
同时检查是否有父进程在等待,如果有的话向其发消息,并去除其`WAITING`标识.
9. 检查是否有子进程,如果有的话将其父进程设为`INIT`.
for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
if (!(rmp->mp_flags & IN_USE)) continue;
if (rmp->mp_tracer == proc_nr) {
/* This child's tracer died. Do something sensible. */
tracer_died(rmp);
}
if (rmp->mp_parent == proc_nr) {
/* 'rmp' now points to a child to be disinherited. */
rmp->mp_parent = INIT_PROC_NR;
/* Notify new parent. */
if (rmp->mp_flags & ZOMBIE)
check_parent(rmp, TRUE /*try_cleanup*/);
}
}
等到VFS完成stop操作后通知pm,pm执行exit_restart()
,做以下事情:
1. 通过`sched_stop`停止进程参与调度,置`mp_scheduler`为`NONE`;
rmp->mp_scheduler = NONE;
2. 如果要结束的是用户进程则在此执行 `sys_clear()`清除用户进程地址空间,移除`endpoint`, 重置`timer`,等.
3. 调用`vm_exit()`释放占用的内存空间.
if(vmp->vm_flags & VMF_HAS_DMA) {
/* DMA设备 */
release_dma(vmp);
} else if(vmp->vm_flags & VMF_HASPT) {
/* Free pagetable and pages allocated by pt code. */
SANITYCHECK(SCL_DETAIL);
free_proc(vmp);
SANITYCHECK(SCL_DETAIL);
} else {
/* Free the data and stack segments. */
free_mem(vmp->vm_arch.vm_seg[D].mem_phys,
vmp->vm_arch.vm_seg[S].mem_vir +
vmp->vm_arch.vm_seg[S].mem_len -
vmp->vm_arch.vm_seg[D].mem_vir);
}
SANITYCHECK(SCL_DETAIL);
/* Reset process slot fields. */
clear_proc(vmp);
SANITYCHECK(SCL_FUNCTIONS);
return OK;
4. 如果有`tracer`, 通知它已完成.
5. 通过`cleanup()`释放进程表,重初始化`mproc`关键标识位.
rmp->mp_pid = 0;
rmp->mp_flags = 0;
rmp->mp_child_utime = 0;
rmp->mp_child_stime = 0;