孤儿进程与僵尸进程
在Linux当中,子进程是由父进程创建的,子进程再创建新的进程。子进程的结束和父进程的运行是一个异步的过程,即父进程永远无法预测子进程到底什么时候结束。unix系统提供了一种机制可以让父进程获得子进程结束时的状态信息,也就是说在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存,但是仍然为其保留一定的信息,如进程号、退出状态、运行时间等。那么,当一个子进程完成它的工作终止之后,它的父进程就要调用wait()或者waitpid()系统调用来取得子进程的终止状态。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程完成对它们状态收集工作。
僵尸进程:一个进程使用 fork创建子进程,如果子进程退出,而父进程没有调用wait或waitpid函数获取子进程的状态信息,那么子进程的进程描述符仍然会保存在系统中。这种进程称为僵尸进程。
僵尸进程的危害:
在子进程退出时,如果父进程不调用wait或waitpid函数的话,那么系统保留的子进程的信息就不会被释放,其子进程号会一直被占用,但是系统所能使用的进程号是有限的,如果产生大量的僵尸进程,最终可能导致系统没有可用的进程号,从而不能产生新的进程。寻求如何消灭系统中大量的僵死进程时,就是把产生大量僵死进程的那个父进程kill掉,即通过kill发送SIGTERM或者SIGKILL信号。父进程被kill掉之后,它产生的僵死进程就变成了孤儿进程,这些孤儿进程会被init进程接管,init进程会wait()这些孤儿进程,释放它们占用的系统进程表中的资源。
僵尸进程的解决方法:
- 使用signal函数显式忽略SIGCHLD信号
- 调用wait()函数或者waitpid()函数处理僵尸进程
- fork()两次,父进程fork子进程后继续执行,子进程fork一个孙进程后退出,此时孙进程会被init进程接管,避免僵尸进程
守护进程
守护进程(daemon),是一种运行在后台的特殊进程,它独立于控制终端 ,并周期性地执行某项任务或等待处理某些发生的事件。守护进程可以由一个普通的进程按照守护进程的特性改造而来。基本的流程如下:

1)首先应该屏蔽一些有关控制终端操作的信息,防止在守护进程还没有正常运行起来前受到控制终端的干扰退出或挂起。
2) 前台转后台:首先在普通进程中调用fork函数之后,使父进程终止,让子进程继续执行,此时子进程称为孤儿进程,由于子进程是父进程的完全copy,而子进程又在后台运行,完成“脱壳”。
3)脱离控制终端,登录会话和进程组。如果想要普通进程脱离控制终端,登录会话和进程组,不受他们影响,可以使用setsid()设置新会话的首进程,使其与原来的登录会话和进程组自动分离。代码如下:
if (-1 == setsid()) exit(0);
setsid()函数说明如下:
pid_t setsid(void);
返回值:成功返回进程组ID,出错返回-1;
函数说明:如果,调用setsid的进程不是一个进程组的组长,此函数创建一个新的会话期。结果为
(1)此进程变成新会话的会话首进程,此时,此进程是该新会话组中的唯一进程
(2)此进程变成一个新进程组的组长进程。新进程组ID是该调用进程的进程ID
(3)此进程没有控制终端,如果在调用setsid前,该进程有控制终端,那么与该终端的联系被解除
4)经过前面的3个步骤,该子进程已经脱离了控制终端,原来的登录会话和进程,似乎已经完成从普通进程到守护进程的转换,但是,对于某些系统,如SVR4,当会话首进程打开一个尚未与任何会话相关联的终端设备,此设备会自动作为控制终端分配给该会话。所以,我们需要采用不再让该子进程称为会话首进程的方式来禁止进程重新打开关联的控制终端。具体方法为再次调用fork函数,该fork函数执行后,子进程结束,那么孙子进程就不再是会话首进程,避免会话再次被关联到控制终端。当需要注意的是,当会话首进程退出的时候可能会向其所在的会话的所有进程发送SIGHUP信号,而SIGHUP信号的默认处理函数是结束进程,为了防止孙子进程意外结束,所以要忽略SIGHUP信号。
5)最后一步就是改变工作目录到根目录。因为进程活动时,其工作目录所在的文件系统不能被卸下,一般需要将工作目录改变到根目录。
6)重设文件创建掩模 (一些进程不用)
进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0);
补充:
操作系统的fork进程返回值?
fork()是创建进程函数,子进程创建成功后,fork是返回两个值,一个代表父进程,一个代表子进程:代表父进程的值是一串数字,这串数字是子进程的ID(地址);一个代表子进程,值为0。
本文深入解析Linux系统中孤儿进程与僵尸进程的概念,探讨其产生原因及危害,同时提供有效的解决方案,包括使用wait函数和守护进程技巧。
1204

被折叠的 条评论
为什么被折叠?



