linux进程管理(5)---进程消亡
一、目的
本文将讲述进程是如何消亡的。一个进程既有父进程又有子进程,因此进程消亡时,既要通知父进程,也要安排好子进程。
当前进程消亡时主要做了三件大事:释放当前进程占用的资源;为当前进程的子进程重新寻找“养父”;通知当前进程的父进程,释放当前进程剩下的资源。
当前进程释放掉大多数进程资源后,只保留内核栈、structtask_struct数据结构;剩下的资源由父进程负责释放。
linux调用sys_exit()、sys_wait4()实现进程的消亡,代码可以在kernel/exit.c中找到。
二、当前进程释放自身资源
当前进程使用sys_exit()->do_exit()释放进程占用的资源,处理过程如下:
1、调用in_interrupt()检查中断服务程序是否调用了do_exit()(只有进程才能主动调用sys_exit(),中断服务程序在任何时候都不能调用do_exit());
2、进程0不能消亡,因此检查当前进程的pid是否为0(即idle进程);
3、调用exit_mm()释放内存地址空间;
4、设置进程退出码,父进程将会获取;
5、调用exit_mm()释放内存地址空间;
6、如果进程排队等候IPC信号,则调用exit_sem()离开队列;
7、调用exit_files()和exit_fs()分别递减文件描述符、文件系统数据的引用计数;如果某个引用计数为零,则释放相应的资源;
8、调用exit_task_namespaces()释放命名空间;
9、调用check_stack_usage()检查进程内核栈的使用情况,并调用exit_thread()释放structthread_info结构体;
10、调用exit_notify()->forget_original_parent()给当前进程的所有子进程按照以下规则重新寻找“养父”;
a)如果当前进程是一个线程,养父为同一线程组中的下一个线程;
b)养父是当前进程的祖先进程;
c)养父是init进程;
11、调用exit_notify()->do_notify_parent()向当前进程的养父发送信号,通知父进程当前进程即将消亡,让父进程来处理(父进程调用sys_waitpid释放剩下的资源)。
三、养父进程释放剩下的资源
养父进程使用sys_waitpid()->sys_wait4()处理消亡的子进程,处理过程如下:
1、在当前进程的栈中定义一个structwait_opts wo数据结构,重点关注wait_queue_tchild_wait成员;
2、调用add_wait_queue()将wo的child_wait成员加入到当前进程的wait_chldexit队列中;
3、设置当前进程的运行状态为可中断状态(INTERRUPTIBLE);
4、如果子进程满足以下条件:
a)子进程的状态为EXIT_DEAD,跳转到5);
b)子进程的状态为EXIT_ZOMBIE,则调用wait_task_zombie()处理子进程消亡,跳转到5);
c)子进程的状态为STOPPED,则调用wait_task_stopped()处理子进程的消亡,跳转到5);
d)否则,调用wait_task_continued()继续执行;调用schedule()将当前进程睡眠,等到下一次被调度时,程序跳转到4)执行。
5、设置当前进程的运行状态为TASK_RUNNING;
6、调用remove_wait_queue()将child_wait从wait_chldexit队列中移除。
四、总结
进程消亡时,既要通知父进程,也要安排好子进程。
版权声明:
原创作品,如非商业性转载,请注明出处;如商业性转载出版,请与作者联系。