先来说下我理解的守护进程:守护进程没有控制终端,我觉得可以把它理解为一个后台进程。
本篇文章假设读者知道什么是进程组与会话。
下面看一下unix环境高级编程中守护进程的创建流程:
1.首先在进程中调用fork进程,这样就能保证子进程不是进程的组长进程(因为进程组的组长进程不能调用setsid创建新的会话),然后结束掉父进程。这时子进程就变成了会话首进程,并且创建了一个会话。
2.接下来在会话首进程中忽略掉sighup信号,这样在接下来调用fork创建的子进程中也会继承对该信号忽略的处理。因为我们要创建一个没有控制终端的进程,所以我们可以这样做:在会话首进程中调用fork创建一个子进程,然后再结束掉会话首进程,因为会话首进程是负责和终端建立联系的,当我们把会话首进程结束掉之后,那么该会话也就没有控制终端了,结束掉会话首进程之后,子进程会收到sighup信号,因为这个对这个信号的默认处理为结束掉进程,所以如果前面我们不在会话首进程中把对该信号的动作设为忽略就会结束掉刚创建的子进程。当把会话首进程结束掉之后,那么该子进程就会变为该会话中的唯一一个进程,且没有控制终端,这个子进程就是我们要创建的守护进程。
下面是unix坏境高级编程中创建守护进程的源码:
上面说到当会话首进程结束之后,其子进程会接收到sighup信号,接下来我们看看什么情况下一个进程会接收到sighup信号:
SIGHUP会在以下3种情况下被发送给相应的进程:
1、终端关闭时,该信号被发送到session首进程以及作为job提交的进程(即用 & 符号提交的进程)
2、session首进程退出时,该信号被发送到该session中的前台进程组和后台进程组中的每一个进程
3、若进程的退出,导致一个进程组变成了孤儿进程组,且新出现的孤儿进程组中有进程处于停止状态,则SIGHUP和SIGCONT信号会按顺序先后发送到新孤儿进程组中的每一个进程。
注:孤儿进程组:该组中每个成员的父进程要么是该进程组的成员要么不是该会话的成员。