美文网首页
Linux内核设计与实现 进程管理3: 进程终止

Linux内核设计与实现 进程管理3: 进程终止

作者: 虹桥过夜好无聊 | 来源:发表于2017-12-21 22:47 被阅读0次

进程终止

        当一个进程显示地调用*exit()函数,或者隐式地在main()函数中返回(C 编译器自动地在main()后调用exit()函数)时,进程即终止了。

        进程也有可能非自愿地终止。当进程收到某些信号或产生异常,并且无法忽略,改变处理方式时。进程依照默认的做法终止。

        不管进程以什么方式终止,都要调用do_exit()函数,这个函数定义在<kernel/exit.c>中。

do_exit() 1

           1. 将进程描述符的flags成员设置为PF_EXITING。

           2.  调用del_timer_sync()益处内核定时器。保证不会再有定时器和定时器处理程序运行。

           3. profile_task_exit()效果不明。  ???

           4. 对ptrace的操作暂时不知。  ???

do_exit() 2

             5.acct_process()书写计数信息。

             6.__exit_mm()释放进程描述符的mm_struct成员。当该地址空间不被其他进程分享时,顺便释放此块内存。

             7.exit_sem()如果该进程正在排队等待IPC信号,那么退出等待队列。

             8.exit_notify()向父进程发送信号,并且将子进程的父进程设置为同一线程组的其他线程,或者是init进程。

             9.schedule()调度,运行到其他进程。

        中止进程将转变为TASK_ZOMBLE状态,其唯一对内存空间的利用就是内核栈,因为保留了thread_info和task_struct两个数据结构,直到其父进程调用了wait4()。

移除进程描述符

        wait()函数族基本做法,调用<kernel/exit.c>中的release_task()函数(详见《Linux内核设计与实现》第37页):

release_task() 1 release_task() 2

        1.调用free_uid()来减少该进程拥有者的进程使用计数,当该计数为0,则该用户的cache被销毁。

        2.调用unhash_process()从pidhash上删除该进程(其实并未显式地调用该函数,而是将其语句分散开调用了),同时也要从task_list中删除       该进程。

        3.如果这个进程正在被ptrace追踪,将追踪进程的父进程重设为其最初的父进程并将它从ptrace_list上删除。

        4.最后,调用put_task_struct释放进程内核栈和thread_info结构所占的页,并释放task_struct所占的slab高速缓存。

        关于slab可在学习slab机制

无父进程的困境

        与《Linux内核设计与实现》第二版中表述不同,do_exit()并未调用notify_parent(),而是调用了上文提过的exit_notify(),进而调用forget_original_parent()来完成改变父进程的工作。

exit_notify() 片段

        上图中可以看到,exit_notify()函数甚至还处理了因为本进程退出而产生孤儿进程组的情况。其实exit_notify()还囊括了许多情况,不一一列举。下图为forget_original_parent()函数:


forget_original_parent()

        需要注意的是 1.child_reaptr 指向init进程。 2. list_for_each_safe(){} 作用未知,疑似为某种循环体。 ????

相关文章

网友评论

      本文标题:Linux内核设计与实现 进程管理3: 进程终止

      本文链接:https://www.haomeiwen.com/subject/ffjzwxtx.html