Chinaunix

标题: How to Daemonize in Linux [打印本页]

作者: kevinspace    时间: 2009-05-18 15:06
标题: How to Daemonize in Linux

How to Daemonize in Linux
One of the things I keep running across is Linux daemons that don’t properly daemonize themselves. To properly daemonize, the following steps must be followed.

Failure to do any of these steps will lead to a daemon process that can misbehave. The typical symptoms are as follows.

Simple Example
The following example program performs the bare minimum steps required to launch a daemon process.
#include
#include
#include
#include
#include
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
static void daemonize(void)
{
    pid_t pid, sid;
    /* already a daemon */
    if ( getppid() == 1 ) return;
    /* Fork off the parent process */
    pid = fork();
    if (pid  0) {
        exit(EXIT_SUCCESS);
    }
    /* At this point we are executing as the child process */
    /* Change the file mode mask */
    umask(0);
    /* Create a new SID for the child process */
    sid = setsid();
    if (sid daemonize();
    /* Now we are a daemon -- do the work for which we were paid */
    return 0;
}
It has been brought to my attention that a second call to fork() may be required to fully detach the process from the controller terminal (in other words: fork, setsid, fork). This does not seem to be required in Linux. A second fork would not cause any problems, although it would complicate the child/parent signalling below.
A More Useful Example
The following program extends the basic daemon by adding the following features.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* Change this to whatever your daemon is called */
#define DAEMON_NAME "mydaemon"
/* Change this to the user under which to run */
#define RUN_AS_USER "daemon"
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
static void child_handler(int signum)
{
    switch(signum) {
    case SIGALRM: exit(EXIT_FAILURE); break;
    case SIGUSR1: exit(EXIT_SUCCESS); break;
    case SIGCHLD: exit(EXIT_FAILURE); break;
    }
}
static void daemonize( const char *lockfile )
{
    pid_t pid, sid, parent;
    int lfp = -1;
    /* already a daemon */
    if ( getppid() == 1 ) return;
    /* Create the lock file as the current user */
    if ( lockfile && lockfile[0] ) {
        lfp = open(lockfile,O_RDWR|O_CREAT,0640);
        if ( lfp pw_uid );
        }
    }
    /* Trap signals that we expect to recieve */
    signal(SIGCHLD,child_handler);
    signal(SIGUSR1,child_handler);
    signal(SIGALRM,child_handler);
    /* Fork off the parent process */
    pid = fork();
    if (pid  0) {
        /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
           for two seconds to elapse (SIGALRM).  pause() should not return. */
        alarm(2);
        pause();
        exit(EXIT_FAILURE);
    }
    /* At this point we are executing as the child process */
    parent = getppid();
    /* Cancel certain signals */
    signal(SIGCHLD,SIG_DFL); /* A child process dies */
    signal(SIGTSTP,SIG_IGN); /* Various TTY signals */
    signal(SIGTTOU,SIG_IGN);
    signal(SIGTTIN,SIG_IGN);
    signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */
    signal(SIGTERM,SIG_DFL); /* Die on SIGTERM */
    /* Change the file mode mask */
    umask(0);
    /* Create a new SID for the child process */
    sid = setsid();
    if (sid Daemonize */
    daemonize( "/var/lock/subsys/" DAEMON_NAME );
    /* Now we are a daemon -- do the work for which we were paid */
    /* Finish up */
    syslog( LOG_NOTICE, "terminated" );
    closelog();
    return 0;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/93615/showart_1932182.html




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2