关闭

APUE函数笔记十一: 守护进程

463人阅读 评论(0) 收藏 举报

第十三章  守护进程:

#include <syslog.h>
void openlog(const char * ident, int option, int facility);
void syslog(int priority, const char * format, ...);
void closelog(void);
int setlogmask(int maskpri);
    return previous mask priority
    option:
        LOG_CONS, LOG_NDELAY, LOG_NOWAIT, 
        LOG_ODELAY, LOG_PERROR, LOG_PID
    facility:
        LOG_AUTH,   LOG_AUTHPRIV, LOG_CRON,   LOG_DAEMON, 
        LOG_FTP,    LOG_KERN,     LOG_LOCAL0, LOG_LOCAL1, 
        LOG_LOCAL2, LOG_LOCAL3,   LOG_LOCAL4, LOG_LOCAL5, 
        LOG_LOCAL6, LOG_LOCAL7,   LOG_LPR,    LOG_MAIL, 
        LOG_NEWS,   LOG_SYSLOG,   LOG_USER,   LOG_UUCP
    level:
        LOG_EMERG,   LOG_ALERT,  LOG_CRIT, LOG_ERR, 
        LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG
    priority:
        facility | level
    %m: ("%s", strerror(errno))

#include <syslog.h>
#include <stdarg.h>
void vsyslog(int priority, const char * format, va_list arg);

示例:

#ifndef __DAEMON_H__
#define __DAEMON_H__


#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/resource.h>

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

    /*
     * clear file creation mask
     */
    umask(0);

    /*
     * get maximum number of file descriptors
     */
    if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
        printf("%s: cannot get file limit\n", cmd);
        exit(1);
    }

    /*
     * become a session leader to lose controlling TTY
     */
    if ((pid = fork()) < 0) {
        printf("%s: cannot fork\n", cmd);
        exit(1);
    }
    else if (pid > 0) {
        exit(0);
    }
    setsid();

    /*
     * ensure future opens wonnot allocate controlling TTYs
     */
    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGHUP, &sa, NULL) < 0) {
        printf("%s: cannot ignore SIGHUP\n", cmd);
        exit(1);
    }
    if ((pid = fork()) < 0) {
        printf("%s: cannot fork\n", cmd);
        exit(1);
    }
    else if (pid > 0) {
        exit(0);
    }

    /*
     * change the current working directory to the root so
     * we wonnot prevent file systems from being unmounted
     */
    if (chdir("/") < 0) {
        printf("%s: cannot change directory to /\n", cmd);
        exit(1);
    }

    /*
     * close all open file destriptors
     */
    if (rl.rlim_max == RLIM_INFINITY) {
        rl.rlim_max = 1024;
    }
    for (i = 0; i < rl.rlim_max; ++i) {
        close(i);
    }

    /*
     * attach file descriptors 0, 1, 2 to /dev/null
     */
    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);

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


#endif

#ifndef __LOCKFILE_H__
#define __LOCKFILE_H__


#include <fcntl.h>
#include <unistd.h>

int 
lockfile(int fd)
{
    struct flock fl;

    fl.l_type = F_WRLCK;
    fl.l_start = 0;
    fl.l_whence = SEEK_SET;
    fl.l_len = 0;
    return(fcntl(fd, F_SETLK, &fl));
}


#endif

#ifndef __SINGLE_H__
#define __SINGLE_H__


#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/stat.h>

#include "lockfile.h"

#define LOCKFILE "/var/run/mydaemon.pid"
#define LOCKMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int 
already_running(void)
{
    int   fd;
    char  buf[16];

    if ((fd = open(LOCKFILE, O_RDWR | O_CREAT, LOCKMODE)) < 0) {
        syslog(LOG_ERR, "cannot open %s: %s", LOCKFILE, strerror(errno));
        exit(1);
    }
    if (lockfile(fd) < 0) {
        if (errno == EACCES || errno == EAGAIN) {
            close(fd);
            return(1);
        }
        syslog(LOG_ERR, "cannot lock %s: %s", LOCKFILE, strerror(errno));
        exit(1);
    }
    ftruncate(fd, 0);
    sprintf(buf, "%ld", (long)getpid());
    write(fd, buf, strlen(buf) + 1);
    return(0);
}


#endif

#include <fcntl.h>
#include <unistd.h>

#include "daemon.h"

int 
main(void)
{
    FILE * fp;
    char * p;

    daemonize("getlog");
    p = getlogin();
    fp = fopen("/tmp/getlog.txt", "w");
    if (fp != NULL) {
        if (p == NULL) {
            fprintf(fp, "no login name\n");
        }
        else {
            fprintf(fp, "login name: %s\n", p);
        }
    }
    exit(0);
}

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <pthread.h>

#include "daemon.h"
#include "single.h"

void 
reread(void)
{
    /* ... */
}

void 
sig_term(int signo)
{
    syslog(LOG_INFO, "got SIGTERM, exiting");
    exit(0);
}

void 
sig_hup(int signo)
{
    syslog(LOG_INFO, "re-reading configuration file");
    reread();
}

int 
main(int argc, char * argv[])
{
    char             * cmd;
    struct sigaction   sa;

    if ((cmd = strrchr(argv[0], '/')) == NULL) {
        cmd = argv[0];
    }
    else {
        ++cmd;
    }

    /*
     * become a daemon
     */
    daemonize(cmd);

    /*
     * make sure only one copy of the daemon is running
     */
    if (already_running()) {
        syslog(LOG_ERR, "daemon already running");
        exit(1);
    }

    /*
     * handle signals of interest
     */
    sa.sa_handler = sig_term;
    sigemptyset(&sa.sa_mask);
    sigaddset(&sa.sa_mask, SIGHUP);
    sa.sa_flags = 0;
    if (sigaction(SIGTERM, &sa, NULL) < 0) {
        syslog(LOG_ERR, "cannot catch SIGTERM: %s", strerror(errno));
        exit(1);
    }
    sa.sa_handler = sig_hup;
    sigemptyset(&sa.sa_mask);
    sigaddset(&sa.sa_mask, SIGTERM);
    sa.sa_flags = 0;
    if (sigaction(SIGHUP, &sa, NULL) < 0) {
        syslog(LOG_ERR, "cannot catch SIGHUP: %s", strerror(errno));
        exit(1);
    }

    /*
     * proceed with the rest of the daemon
     */
    /* ... */
    exit(0);
}

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <pthread.h>

#include "daemon.h"
#include "single.h"

sigset_t   mask;

void 
reread(void)
{
    /* ... */
}

void * 
thr_fn(void * arg)
{
    int   err;
    int   signo;

    for (;;) {
        if ((err = sigwait(&mask, &signo)) != 0) {
            syslog(LOG_ERR, "sigwait failded");
            exit(1);
        }
        switch (signo) {
            case SIGHUP:
            {
                syslog(LOG_INFO, "re-reading configuration file");
                reread();
                break;
            }
            case SIGTERM:
            {
                syslog(LOG_INFO, "got SIGTERM, exiting");
                exit(0);
            }
            default:
            {
                syslog(LOG_INFO, "unexpected signal %d\n", signo);
                break;
            }
        }
    }
    return(NULL);
}

int 
main(int argc, char * argv[])
{
    int                err;
    char             * cmd;
    pthread_t          tid;
    struct sigaction   sa;

    if ((cmd = strrchr(argv[0], '/')) == NULL) {
        cmd = argv[0];
    }
    else {
        ++cmd;
    }

    /*
     * become a daemon
     */
    daemonize(cmd);

    /*
     * make sure only one copy of the daemon is running
     */
    if (already_running()) {
        syslog(LOG_ERR, "daemon already running");
        exit(1);
    }

    /*
     * restore SIGHUP default and block all signals
     */
    sa.sa_handler = SIG_DFL;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGHUP, &sa, NULL) < 0) {
        printf("%s: cannot restore SIGHUP default\n", strerror(errno));
        exit(1);
    }
    sigfillset(&mask);
    if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0) {
        printf("%s: SIG_BLOCK error\n", strerror(errno));
        exit(1);
    }

    /*
     * create a thread to handle SIGHUP and SIGTERM
     */
    if ((err = pthread_create(&tid, NULL, thr_fn, NULL)) != 0) {
        printf("%s: cannot create thread\n", strerror(errno));
        exit(1);
    }

    /*
     * proceed with the rest of the daemon
     */
    /* ... */
    exit(0);
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:155140次
    • 积分:3258
    • 等级:
    • 排名:第10419名
    • 原创:167篇
    • 转载:10篇
    • 译文:0篇
    • 评论:41条
    文章分类
    最新评论