Linux进程中fork与exec区别、探究进程结束过程

Linux进程中有fork和exec两种方法。这里就详细拆解login进程说道fork与exec两种方法的区别。
这里写图片描述
一个系统登录本来有tty1至tty6 六个mingetty进程,这六个虚拟控制台,可以通过Ctrl+Alt+F1~F6分别切换到他们对应的“login:”提示符下。由于我已经输入用户名和密码,这时候一个mingetty进程执行exec方法转变成login进程。这样从图片中能看出,执行命令

ps -ef|grep "mingett[y]"

{grep 命令参数中,通过将最后一个字母y写成[y]的方法,可以确保grep进程名的结果中不包有与进程名不符的信息}
只找到了五个虚拟控制台的mingetty进程,其中tty1的mingetty进程不存在。这个就是exec方法执行结果。
从运行结果可以看出bash进程作为login进程的子进程开始启动的。但是bash进程并不是从login进程直接fork出来的。如下图
这里写图片描述
可以看出,fork生成的子进程是一个与正在运行的进程(login进程)完全相同的副本。login进程通过fork生成一个自身的副本后,又在子进程中通过exec启动bash进程。
通过如下图对比exec和fork方法
这里写图片描述

总结一下:fork和exec分别是进程的分身和变身

探究一下进程的结束过程
父进程login通过执行login.c源码中1202行的wait函数,一直休眠到子进程结束,如下所示,通过ps命令确认进程的状态,可以看到附加的表示休眠状态的S符号。
这里写图片描述
这时候在已经登录的虚拟控台上显示的bash命令符处,输入exit进行用户注销。此时,通过exit()系统调用,bash进程被终止,同时发送CHLD信号给父进程login。

接收到CHLD信号的父进程login会退出wait函数,同时结束进程。

另一方面,子进程向父进程发送CHLD信号,直到父进程接收为止,子进程都处于“僵尸进程”的状态。如果父进程设置为忽略CHLD信号,子进程就会一直保持僵尸状态。

通过ps aux来查看进程状态时,僵尸状态会被标记为Z,信息末尾会显示<default>.
其实对于bash进程在被exit终止后的一系列可以用如下图表示
这里写图片描述
从之前ps命令的输出中可以看到,login进程的父进程是进程ID为1的init进程。因此,init进程将会接收CHLD信号,这时候login进程就可以从僵尸状态中解放出来。

另一方面,接收到CHLD信号后,init进程就会检测到login进程(或原始的mingetty进程)已经终止了,于是会再度启动新的mingetty进程。

猜你喜欢

转载自blog.csdn.net/tbc123tbc/article/details/80931410