`
nil-zhang
  • 浏览: 50478 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

如何编写一个可靠的linux守护进程

阅读更多
    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)
    所以根据waitpid返回的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)重启工作进程。所以守护进程和工作进程的实现应该是下面的代码逻辑:
// 守护进程(父进程)
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);
}
     对于第二个问题:守护进程的监控可以用daemontools工具集中的supervise来监控,也可以自己实现,但是不能只是通过另外一个应用程序去做,因为做守护的进程自身也需要被守护,如此循环解决不了问题。这个时候就要借助于linux系统的init进程了,因为init进程是不能被信号kill掉的(强大到无视SIGKILL)。
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.
    所以让init进程来守护我们的应用程序是最可靠的,看看supervise的作法:
    在/etc/inittab中添加如下一行:
SV1:23:respawn:/usr/local/bin/svscanboot
    每行用“:”分隔开为4个部分:
        id - 该行的标识,自定义的名称SV1。
        runlevels - 该行为应该发生的运行级的列表,这里在level 2和level 3下运行。
        action - 应发生的行为,respawn表示init应该监视这个进程,即使其结束后也应该被重新启动。
        process - 应由init启动的程序的路径。
    修改完成后,可以通过$kill -HUP 1 来立刻生效。
    解决了上面两个问题,守护进程和工作进程提供7 * 24小时的运行才是有保证的。Have fun!    
 
0
0
分享到:
评论
1 楼 chinaagan 2013-02-18  
可以考虑两个进程,互相监控

相关推荐

    Qt编写守护进程

    本篇文章提供一个软件实现守护进程的办法,原理就是udp通信,单独写个守护进程程序,专门负责检测主程序是否存在,不存在则启动。主程序只需要启动live类监听端口,收到hello就回复ok就行。 为了使得兼容任意程序,...

    Linux 通用 WebAdmin (webui) 开发框架-C语言 源码

    是一个免费的开源框架,用于为Linux系统的快速搭建统一、稳定、易用的Web管理系统。 WebAdmin系统由三部分组成:WEB图形用户接口、WebAdmin守护进程和进程监视程序。Web图形用户接口(WebGUI)是WebAdmin系统的...

    quagga-1.2.1.tar.gz

    Quagga软件原名是Zebra是由一个日本开发团队编写的一个以GNU版权方式发布的软件。Quagga项目开始与1996年,当前版本是0.98.4版 可以使用Quagga将linux机器打造成一台功能完备的路由器。 Quagga支持的路由协议 ...

    quagga-1.2.2.tar.gz

    Quagga软件原名是Zebra是由一个日本开发团队编写的一个以GNU版权方式发布的软件。Quagga项目开始与1996年,当前版本是0.98.4版 可以使用Quagga将linux机器打造成一台功能完备的路由器。 Quagga支持的路由协议 ...

    Linux邮件服务器软件比较.docx

    安全性:Postfix使用多层防护措施防X攻击者来保护本地系统,几乎每 一个Postfix守护进程都能运行在固定低权限的chroot之下,在网络和安全敏感 的本地投递程序之间没有直接的路径—一个攻击者必须首先突破若干个其他...

    基于Linux的多进程MDSL研究与设计 (2013年)

    该设计基于Linux操作系统(2.6内核),采用了多进程方式降低系统藕合度,提高系统可靠性,并采用双机兄余和守护进程等设计保证系统稳定性,同时采用了多线程管理方式实现远程控制单元。实践表明,新系统拥有更好的可靠性...

    linux programming instances网络编程教程 附源代码

    实例十 守护进程 实例十一 普通文件传输协议(tftp) 附录 附录一 gcc命令选项 1.使用语法 2.选项 附录二 makefile文件的编写方法 1.makefile文件的基本结构 2.makefile文件编写规则 3.makefile变量 4.假象...

    rsync+inotify实现实时同步

    其次,rsync不能实时的去监测、同步数据,虽然它可以通过linux守护进程的方式进行触发同 步,但是两次触发动作一定会有时间差,这样就导致了服务端和客户端数据可能出现不一致,无法在应用故障时完全的恢复数据。...

    基于Mailserver性能监视系统

    电子邮件是整个互联网行业重要的组成部分。据统计,四分之三以上的用户上网的主要目的是收发邮件,每天有十数亿封电子邮件在全球传递。...关键词:邮件服务器性能监视,多进程,守护进程,共享内存,信号量,PRO*C

    Kiwi-Syslog日志服务器搭建.doc

    配置Rsyslog守护进程为客户端: # vi /etc/rsyslog.conf 添加以下声明,将IP地址替换为你的远程rsyslog服务器的IP地址: *.* @192.168.4.14:514 // UDP端口 ( 若需要可靠地协议,*.* @@192.168.4.14:514//TCP端口 ...

    UNIX环境高级编程-中文第三版

    在本书第2版出版后的8年中,UNIX行业发生了巨大的变化,特别是影响LJNIX...本书帮助了几代程序员写出强大、高性能、可靠的代码,内容**,概念清晰,阐述精辟,对于所有层次UNIX Linux程序员都是一本不可或缺的参考书。

    UNIX环境高级编程_第二版中文

    13.6 守护进程的惯例  13.7 客户进程-服务器进程模型  13.8 小结  习题  第14章 高级I/O  14.1 引言  14.2 非阻塞I/O  14.3 记录锁  14.4 STREAMS  14.5 I/O多路转接  14.5.1 select和pselect...

    UNIX环境高级编程_第2版.part1

     关系、信号、线程、线程控制、守护进程、各种I/O、进程间通信、网络IPC、伪终端等方面的内容,还在  此基础上介绍了多个应用实例,包括如何创建数据库函数库以及如何与网络打印机通信等。此外,还在附  录中给...

    UNIX环境高级编程_第2版.part2

     关系、信号、线程、线程控制、守护进程、各种I/O、进程间通信、网络IPC、伪终端等方面的内容,还在  此基础上介绍了多个应用实例,包括如何创建数据库函数库以及如何与网络打印机通信等。此外,还在附  录中给...

    UNIX环境高级编程

    关系、信号、线程、线程控制、守护进程、各种I/O、进程间通信、网络IPC、伪终端等方面的内容,还在 此基础上介绍了多个应用实例,包括如何创建数据库函数库以及如何与网络打印机通信等。此外,还在附 录中给出了函数...

    UNIX环境高级编程(第二版中文)

    13.6 守护进程的惯例 350 13.7 客户进程-服务器进程模型 354 13.8 小结 354 习题 354 第14章 高级I/O 355 14.1 引言 355 14.2 非阻塞I/O 355 14.3 记录锁 357 14.4 STREAMS 370 14.5 I/O多路转接...

    unix环境编程电子书

    守护进程 341 13.1 引言 341 13.2 守护进程的特征 341 13.3 编程规则 342 13.4 出错记录 345 13.5 单实例守护进程 348 13.6 守护进程的惯例 350 13.7 客户进程-服务器进程模型 354 13.8 小结 354 ...

    powermonius:与功耗保持一致。 只需用电池即可运行所需的电量

    我厌倦了那些小的云同步守护进程,而弟兄们在戴上公路战士帽子时总是旋转磁盘并唤醒我可怜的空闲CPU。 在尝试了start-stop-programs模块之后,我发现它有点缺乏可靠性。 受这个概念的启发,我现在有一个借口尝试Go...

Global site tag (gtag.js) - Google Analytics