linux服务端程序都需要提供7 * 24不间断的服务,如何保证工作进程一直不退出或者不被kill掉,常见的方法就是启动一个守护进程来检测工作进程的状态,如果发现工作进程退出,就再fork一个出来。一般的实现见下面一段代码:
守护进程fork出工作进程之后,就阻塞在waitpid系统调用,等待工作进程的退出,waitpid返回之后,根据status选择继续fork工作进程还是退出守护进程。status为int型变量,但只用到了低16位(见struct wait),0-6位表示使子进程退出的信号(可以通过 $kill -l 查看信号的值),8-15位表示子进程退出时的返回码(exit或者return的值)。
判断status的状态可以通过下面的宏完成:
1. 对SIGKILL, SIGINT, SIGTERM信号,守护进程直接退出了,没有fork工作进程出来; 2. 守护进程被kill掉了,工作进程就只能裸奔了。 对于第一个问题:SIGKILL有可能是人为($kill -9 pid)发出的,也有可能是工作进程占用内存过多,被OOM掉了(关于OOM参见这里),都不是我们想要的结果,所以工作进程被SIGKILL掉,守护进程一定要将其重启。SIGINT是 CTRL+C 发出的(非daemon模式下),SIGTERM是 $killall servicename(或者 $kill pid)发出的,这两个信号都是在结束进程的时候用到,这个时候工作进程应该捕获被处理这两个信号,正常地退出(return 0;)。而守护进程只有在工作进程正常退出的情况下才完成自己的使命,否则(工作进程被其他信号结束掉,如SIGABRT, SIGKILL, SIGSEGV)重启工作进程。所以守护进程和工作进程的实现应该是下面的代码逻辑:
在/etc/inittab中添加如下一行:
id - 该行的标识,自定义的名称SV1。 runlevels - 该行为应该发生的运行级的列表,这里在level 2和level 3下运行。 action - 应发生的行为,respawn表示init应该监视这个进程,即使其结束后也应该被重新启动。 process - 应由init启动的程序的路径。 修改完成后,可以通过$kill -HUP 1 来立刻生效。 解决了上面两个问题,守护进程和工作进程提供7 * 24小时的运行才是有保证的。Have fun! |