如何编写一个可靠的linux守护进程
来源:互联网 发布:sql select 多张表 编辑:程序博客网 时间:2024/06/10 22:32
linux服务端程序都需要提供7 * 24不间断的服务,如何保证工作进程一直不退出或者不被kill掉,常见的方法就是启动一个守护进程来检测工作进程的状态,如果发现工作进程退出,就再fork一个出来。一般的实现见下面一段代码:
- // 守护进程(父进程)
- int status;
- for ( ; ; ) {
- if ( 0 == ( pid = fork()) ) {
- // 工作进程(子进程)
- run();
- }
- waitpid(-1, &status, 0);
- if (WIFEXITED(status))
- if (WEXITSTATUS(status) == 0)
- exit(0);
- if (WIFSIGNALED(status)) {
- switch (WTERMSIG(status)) {
- case SIGKILL:
- exit(0);
- break;
- case SIGINT:
- case SIGTERM:
- exit(1);
- default:
- break;
- }
- }
- }
守护进程fork出工作进程之后,就阻塞在waitpid系统调用,等待工作进程的退出,waitpid返回之后,根据status选择继续fork工作进程还是退出守护进程。status为int型变量,但只用到了低16位(见struct wait),0-6位表示使子进程退出的信号(可以通过 $kill -l 查看信号的值),8-15位表示子进程退出时的返回码(exit或者return的值)。
- struct wait{
- # if __BYTE_ORDER == __LITTLE_ENDIAN
- unsigned int __w_termsig:7; /* Terminating signal. */
- unsigned int __w_coredump:1; /* Set if dumped core. */
- unsigned int __w_retcode:8; /* Return code if exited normally. */
- unsigned int:16;
- # endif /* Little endian. */
- };
判断status的状态可以通过下面的宏完成:
- WIFEXITED(status) //子进程调用exit()或者从main return退出时为true;
- WEXITSTATUS(status) //在WIFEXITED为true时,表示exit()或return的返回码;
- WIFSIGNALED(status) //子进程被信号终止时为true;
- WTERMSIG(status) //在WIFSIGNALED为true时,表示终止子进程信号的值;
- /* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
- #define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
- /* If WIFSIGNALED(STATUS), the terminating signal. */
- #define __WTERMSIG(status) ((status) & 0x7f)
- /* Nonzero if STATUS indicates normal termination. */
- #define __WIFEXITED(status) (__WTERMSIG(status) == 0)
- /* Nonzero if STATUS indicates termination by a signal. */
- #define __WIFSIGNALED(status) \
- (((signed char) (((status) & 0x7f) + 1) >> 1) > 0)
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)重启工作进程。所以守护进程和工作进程的实现应该是下面的代码逻辑:
- // 守护进程(父进程)
- int status;
- for ( ; ; ) {
- if ( 0 == ( pid = fork()) ) {
- // 工作进程(子进程)
- run();
- //信号处理函数signal_handler
- if (sig == SIGTERM || sig == SIGINT) {
- destroy();
- return 0;
- }
- }
- waitpid(-1, &status, 0);
- if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)) exit(0);
- }
- The only signals that can be sent task number one, the init process, are those for which init has explicitly installed signal handlers. This is done to assure the system is not brought down accidentally.
在/etc/inittab中添加如下一行:
- SV1:23:respawn:/usr/local/bin/svscanboot
id - 该行的标识,自定义的名称SV1。
runlevels - 该行为应该发生的运行级的列表,这里在level 2和level 3下运行。
action - 应发生的行为,respawn表示init应该监视这个进程,即使其结束后也应该被重新启动。
process - 应由init启动的程序的路径。
修改完成后,可以通过$kill -HUP 1 来立刻生效。
解决了上面两个问题,守护进程和工作进程提供7 * 24小时的运行才是有保证的。Have fun!转载自:http://nil-zhang.iteye.com/blog/1806356
- 如何编写一个可靠的linux守护进程
- 如何编写一个可靠的linux守护进程
- 如何编写一个可靠的linux守护进程
- 如何编写linux 守护进程
- 如何编写linux守护进程?
- Linux守护进程的编写
- linux-守护进程的编写
- 如何编写一个守护进程daemon
- linux守护进程介绍以及如何编写守护进程
- 如何编写Linux Daemon后台程序(守护进程)
- 如何编写Linux Daemon后台程序(守护进程)
- 如何编写Linux Daemon后台程序(守护进程)
- 如何正确编写linux守护进程
- 编写一个守护进程
- 编写一个守护进程
- 一个简单的守护进程的编写
- 一个简单的守护进程的编写
- linux 守护进程编写
- jQuery Ajax事件-ajaxError(callback)
- 程序员,请停止说这20句话
- 为什么要去创业?
- Tomcat下配置server.xml文件,不必每次都将项目部署到服务器上
- 直接插入排序、折半插入排序、shell插入排序
- 如何编写一个可靠的linux守护进程
- JBoss 系列十七:使用JGroups构建块MessageDispatcher 构建群组通信应用
- sublime Text 3 的教程和一些网站
- 解决安装完Ubuntu系统后启动项中没有Ubuntu的问题
- ASCII码排序JAVA实现
- jQuery Ajax事件-ajaxSend(callback)
- 已经显现了出来的飞秋下载
- 使用select函数的TCP和UDP回射服务器程序
- 它们翻滚着的飞秋下载