8000 exit() · yuanfeiz/minix Wiki · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
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;
Clone this wiki locally
0