操作系统课内实验报告
}
schedule();
exit_signals(tsk); //设置 PF_EXITING smp_mb();
spin_unlock_wait(&tsk->pi_lock);
if (unlikely(in_atomic()))
printk(KERN_INFO \
current->comm, task_pid_nr(current), preempt_count());
acct_update_integrals(tsk); if (tsk->mm) { }
group_dead = atomic_dec_and_test(&tsk->signal->live); if (group_dead) { }
acct_collect(code, group_dead);
#ifdef CONFIG_FUTEX //定义CONFIG_FUTEX if (unlikely(tsk->robust_list))
exit_robust_list(tsk);
hrtimer_cancel(&tsk->signal->real_timer); exit_itimers(tsk->signal); update_hiwater_rss(tsk->mm); update_hiwater_vm(tsk->mm);
#ifdef CONFIG_COMPAT //定义CONFIG_COMPAT if (unlikely(tsk->compat_robust_list))
compat_exit_robust_list(tsk);
#endif #endif
if (group_dead)
tty_audit_exit();
if (unlikely(tsk->audit_context))
21
audit_free(tsk);
操作系统课内实验报告
tsk->exit_code = code; taskstats_exit(tsk, group_dead);
exit_mm(tsk);
if (group_dead)
acct_process();
exit_sem(tsk);
exit_files(tsk); //结束文件任务 exit_fs(tsk);
check_stack_usage(); //检查堆栈使用情况 exit_thread(); cgroup_exit(tsk, 1); exit_keys(tsk);
if (group_dead && tsk->signal->leader)
disassociate_ctty(1);
module_put(task_thread_info(tsk)->exec_domain->module); if (tsk->binfmt)
module_put(tsk->binfmt->module);
proc_exit_connector(tsk);
exit_notify(tsk, group_dead); // 调用exit_notify告知它的祖先进程这个进程已经退出 #ifdef CONFIG_NUMA mpol_put(tsk->mempolicy); tsk->mempolicy = NULL; #endif
#ifdef CONFIG_FUTEX
if (unlikely(!list_empty(&tsk->pi_state_list)))
exit_pi_state_list(tsk);
if (unlikely(current->pi_state_cache))
kfree(current->pi_state_cache);
#endif
debug_check_no_locks_held(tsk); tsk->flags |= PF_EXITPIDONE; if (tsk->io_context)
22
操作系统课内实验报告
exit_io_context();
if (tsk->splice_pipe)
__free_pipe_info(tsk->splice_pipe);
preempt_disable();
/* causes final put_task_struct in finish_task_switch(). */ tsk->state = TASK_DEAD;
schedule(); //调用Shedule释放CPU BUG();
/* Avoid \ */ for (;;)
cpu_relax(); /* For when BUG is null */}
2.5.5 sys_wait4模块
和exec一样,wait是一组函数,而不是一个函数。wait家族中的其他函数最终都是使用一个系统调用sys_wait4实现的,这个系统调用的名字反映出它实现了wait家族中最通用的函数wait4。标准c库libc的实现必须重新组织对于其他wait函数调用的参数,并调用sys_waitpid。
除了处理一些其他内容,sys_wait4——也只有sys_wait4——最终把僵进程消除。然而从应用程序的观点来看,wait和相关函数要检测子孙进程的状态,检测是否有进程死亡了,如果有,到底是哪一个进程,这个进程是怎么死亡的。 检查参数看是否有效,如果无效,报错 “循环”遍历所有的直接子进程,找到与参数PID相匹配的进程。同时更新子孙进程使用的进程的用户时间与系统时间 搜集资源使用信息,将子孙进程的退出状态传到特定的地址中 图2.4 sys_wait4函数流程图
23
如果进程的祖先不是这个进程,通知这个进程的祖先进程 调用release释放进程的pcb 循环 操作系统课内实验报告
asmlinkage long sys_wait4(pid_t upid, int __user *stat_addr, {
struct pid *pid = NULL; enum pid_type type; long ret;
if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
__WNOTHREAD|__WCLONE|__WALL))
int options, struct rusage __user *ru) //设置参数,结构变量
return -EINVAL; //检查wait4的参数是否有效,无效则包错,有效继续执行
if (upid == -1)
type = PIDTYPE_MAX; //找到直接子进程,找到参数与PID相匹配的进程并更新
子孙进程使用的时间和系统信息 else if (upid < 0) {
type = PIDTYPE_PGID; pid = find_get_pid(-upid);
} else if (upid == 0) {
type = PIDTYPE_PGID;
pid = get_pid(task_pgrp(current));
} else /* upid > 0 */ { }
ret = do_wait(type, pid, options | WEXITED, NULL, stat_addr, ru); put_pid(pid);/
/* avoid REGPARM breakage on x86: */
asmlinkage_protect(4, ret, upid, stat_addr, options, ru); return ret; //释放子孙进程PCB }
type = PIDTYPE_PID; pid = find_get_pid(upid);
2.6实验总结
2.6.1实验中的问题与解决过程
1.由于有些知识忘了,一些地方看不懂。最后通过网络资源解决了; 2.分析别人的源代码前后逻辑看来有些困难,需要多看几次;
24