守护进程

一、概念

  守护进程是生存期长的一种进程。它们常常在系统引导安装时启动,仅在系统关闭时才终止。因为它们没有控制终端,所以说它们是在后台运行的。Unix系统有很多守护进程,他们执行日常事务活动。

二、特征

  1、在使用 ps 命令(例如:ps -axj)输出的信息中,进程名使用方括号标记。

  2、进程ID为1的进程是系统守护进程init。

  3、大多数守护进程都已超级用户root特权运行,这也是守护进程没有终端控制的原因。

  4、守护进程有系统守护进程和用户层守护进程。

三、编写规则

  1、首先调用 umask 将文件模式创建屏蔽字设置为一个已知值(通常为0)。

  2、调用 fork ,然后使父进程 exit 。

  3、调用 setsid 创建一个新回话,使调用进程成为 新回话的首进程、成为新进程的组长进程、没有控制终端。

  4、将当前目录更改为根目录。

  5、关闭不再需要的的文件描述符。

  6、某些守护进程打开 /dev/null 使其具有文件描述符0、1、2,这样任何一个试图读标准输入、写标准输出或标准错误的库例程都不会产生任何效果。

/*
 *下面例子函数可供想要初始化为守护进程的程序调用
 */
#include "apue.h"
#include <syslog.h>
#include <fcntl.h>
#include <sys/resource.h>

void daemonize( const char *cmd )
{
    int   i, fd0, fd1, fd2;
    pid_t   pid;
    struct rlimit  rl;
    struct sigaction sa;

    umask(0);

    if( getrlimit(RLIMIT_NOFILE, &rl) < 0 )
        err_quit("%s : can't get file limit ", cmd);

    if( ( pid = fork() ) < 0 )
        err_quit("%s : can't fork ", cmd);
    else if( pid != 0 )
        exit(0);
    setsid();
    sa.sa_handler = SIG_IGN;
    sigemptyset( &sa.sa_mask );
    sa.sa_flags = 0;
    if( sigaction(SIGHUP, &sa, NULL) < 0 )
        err_quit(" %s: can't ignore SIGHUP ", cmd);
    if( ( pid = fork() ) < 0 )
        err_quit("%s : can't fork ", cmd);
    else if( pid != 0 )
        exit(0);

    if( chdir("/") < 0 )
        err_quit(" %s: can't change directory to /  ", cmd);

    if( rl.rlim_max == RLIM_INFINITY )
        rl.rlim_max = 1024;
    for( i = 0; i < rl.rlim_max; i++ )
        close(i);

    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);

    openlog( cmd, LOG_CONS, LOG_DAEMON);
    if( fd0 != 0 || fd1 != 1 || fd2 != 2 ){
        syslog( LOG_ERR, "unexpected file descriptors %d  %d  %d", fd0, fd1, fd2);
        exit(1);
    }
}

参考《UNIX环境高级编程第三版》

原文地址:https://www.cnblogs.com/yinguojin/p/13899641.html