进程调度之exit

有两个点:从RUNNING到ZOMBIE到DEAD的状态转换;另外一个就是通知父进程届时删除进程描述符.

sys_exit
	=>do_exit((error_code&0xff)<<8);
		=>tsk->flags |= PF_EXITING;
		=>tsk->exit_code = code;
		=>exit_mm(tsk);
			=>mm_release(tsk, mm);
				=>if (vfork_done) {
					tsk->vfork_done = NULL;
					complete(vfork_done);
				}
			=>tsk->mm = NULL;
			=>mmput(mm);
				=>if (atomic_dec_and_test(&mm->mm_users))
					exit_aio(mm);
					exit_mmap(mm);
                        =>munlock_vma_pages_all(vma);
                        =>tlb = tlb_gather_mmu(mm, 1);
                        =>end = unmap_vmas(&tlb, vma, 0, -1, &nr_accounted, NULL);
                        =>free_pgtables(tlb, vma, FIRST_USER_ADDRESS, 0);//清除页表
                        =>tlb_finish_mmu(tlb, 0, end);
					if (!list_empty(&mm->mmlist))
						list_del(&mm->mmlist);
					mmdrop(mm);
		=>__exit_files(tsk);
			=>if (files)
				tsk->files = NULL;
				tsk->files = NULL;
		=>__exit_fs(tsk);
		=>exit_thread();
		=>cpuset_exit(tsk);
		=>module_put(task_thread_info(tsk)->exec_domain->module);
		=>if (tsk->binfmt)
			module_put(tsk->binfmt->module);
		=>exit_task_namespaces(tsk);
		=>exit_notify(tsk);//向父进程发送exit信号,父进程可以释放其进程描述符
			=>if (tsk->exit_signal != -1 && thread_group_empty(tsk)) {
				int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;
				do_notify_parent(tsk, signal);
					=>info.si_signo = sig;
					info.si_errno = 0;
					info.si_pid = tsk->pid;
					info.si_uid = tsk->uid;
					=>info.si_status = tsk->exit_code & 0x7f;
					if (tsk->exit_code & 0x80)
						info.si_code = CLD_DUMPED;
					else if (tsk->exit_code & 0x7f)
						info.si_code = CLD_KILLED;
					else {
						info.si_code = CLD_EXITED;
						info.si_status = tsk->exit_code >> 8;
					}

					psig = tsk->parent->sighand;
					=>if (valid_signal(sig) && sig > 0)
						__group_send_sig_info(sig, &info, tsk->parent);//发信号给父进程
					=>__wake_up_parent(tsk, tsk->parent);//唤醒父进程
			} else if (tsk->ptrace) {
				do_notify_parent(tsk, SIGCHLD);
			}
			=>write_lock_irq(&tasklist_lock);//关中断,防止下面的流程被中断打断,如果被打断就调度出去回不来了
			=>state = EXIT_ZOMBIE;//再也没机会被schedule选中而获取CPU资源
			=>if (tsk->exit_signal == -1 && likely(!tsk->ptrace))
				state = EXIT_DEAD;
			=>tsk->exit_state = state;
			=>write_unlock_irq(&tasklist_lock);//开中断,可以被打断了
			=>if (state == EXIT_DEAD)
				release_task(tsk);
		=>tsk->flags |= PF_EXITPIDONE;
		=>preempt_disable();
		=>tsk->state = TASK_DEAD;
		=>schedule();//调度出去,再也回不来,如果回来了,那很不受待见,出问题了
		=>BUG();
		=>for (;;)
			cpu_relax();

do_group_exit会杀死进程组所有进程,里面调用函数zap_other_threads


/*
 * Nuke all other threads in the group.
 */
void zap_other_threads(struct task_struct *p)
{
	struct task_struct *t;

	p->signal->group_stop_count = 0;

	/*通过for循环可以看到如何找到一个线程组的所有子线程*/
	for (t = next_thread(p); t != p; t = next_thread(t)) {
		/*
		 * Don't bother with already dead threads
		 */
		if (t->exit_state)
			continue;

		/* SIGKILL will be handled before any pending SIGSTOP */
		//*所有线程都将执行do_exit函数*/
		sigaddset(&t->pending.signal, SIGKILL);
		signal_wake_up(t, 1);
	}
}


 

 

 

参考学习文章

UNIX再学习 -- exit 和 wait 系列函数
https://blog.youkuaiyun.com/qq_29350001/article/details/70255915

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值