执行完/bin/echo之后,会调动do_exit,销毁子进程:
我们还是先从系统调用exit()说起,先来看exit()的实现,进入到内核态执行sys_exit。
asmlinkage long sys_exit(int error_code)
{
do_exit((error_code&0xff)<< 8);
}
NORET_TYPE void do_exit(long code)
{
struct task_struct *tsk = current;
if (in_interrupt())//中断服务不能中断
panic("Aiee, killing interrupt handler!");
if (!tsk->pid)//空转idle进程是不允许退出的
panic("Attempted to kill the idle task!");
if (tsk->pid == 1)//init进程是不允许退出的
panic("Attempted to kill init!");
tsk->flags |= PF_EXITING;
del_timer_sync(&tsk->real_timer);
fake_volatile:
#ifdef CONFIG_BSD_PROCESS_ACCT
acct_process(code);
#endif
__exit_mm(tsk);//如果通过指针共享,只是减少共享计数mm->mm_users。如果自立门户,则释放mm_struct,vm_struct;释放页目录表,页表
lock_kernel();
sem_exit();//信号相关,看完进程间通信再说
__exit_files(tsk);//如果通过指针共享,只是减少共享计数files->count。如果自立门户,那就要释放files_struct数据结构
__exit_fs(tsk);//如果通过指针共享,只是减少共享计数fs->count。如果自立门户,那就要释放fs_struct数据结构
exit_sighand(tsk);//如果通过指针共享,只是减少共享计数sig->count。如果自立门户,那就要释放signal_struct数据结构
exit_thread();//空函数
if (current->leader)
disassociate_ctty(1);
put_exec_domain(tsk->exec_domain);
if (tsk->binfmt && tsk->binfmt->module)
__MOD_DEC_USE_COUNT(tsk->binfmt->module);
tsk->exit_code = code;
exit_notify();//将当前进程设置为僵死状态;并给父进程发信号;其当前进程的子进程的父进程设置为init进程
schedule();
BUG();
/*
* In order to get rid of the "volatile function does return" message
* I did this little loop that confuses gcc to think do_exit really
* is volatile. In fact it's schedule() that is volatile in some
* circumstances: when current->state = ZOMBIE, schedule() never
* returns.
*
* In fact the natural way to do all this is to have the label and the
* goto right after each other, but I put the fake_volatile label at
* the start of the function just in case something /really/ bad
* happens, and the schedule returns. This way we can try again. I'm
* not paranoid: it's just that everybody is out to get me.
*/
goto fake_volatile;
}
static inline void __exit_mm(struct task_struct * tsk)
{
struct mm_struct * mm = tsk->mm;
mm_release();
if (mm) {
atomic_inc(&mm->mm_count);
if (mm != tsk->active_mm) BUG();
/* more a memory barrier than a real lock */
task_l