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

原创 2012年03月31日 16:05:42

第十三章  守护进程:

#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);
}


相关文章推荐

APUE 笔记 守护进程

1. daemon 是后台进程 后台进程有些是内核的(kernel daemons),通常他们的父进程号是0,他们在系统启动阶段启动;有些是用户层的(user-level daemons),所有...

APUE读书笔记-第13章-守护进程

第13章 守护进程 13.1 引言 *守护进程也称精灵进程(daemon)是生存期较长的一种进程。它们常常在系统自举时启动,仅在系统关闭时才终止。因为它们没有控制终端,所以说它们是在后台运行的。UNI...

APUE------守护进程

守护进程

apue 第十三章 守护进程

守护进程的编程规则: 总体来说:没有控制终端(不会接收到使守护进程终止的信号),那么就要调用setsid使进程成为会话首进程,调用setsid的前提条件是该进程不是进程组组长,因此先fork一次,让父...

APUE中为何创建守护进程时,为何需要2次fork?

1. 创建守护进程的一般步骤(参考链接:http://learn.akae.cn/media/ch34s03.html) #include #include #include void da...
  • ajaxhe
  • ajaxhe
  • 2013年03月28日 23:15
  • 423

[APUE chapter 13] 守护进程

作者:isshe 日期:2016.10.30 邮箱:i.sshe@outlook.com github: https://github.com/isshe 1. 相关概念 ...

apue学习第二十天——守护进程(第十三章)

Daemon!Here arrived!我们之前对其概念已经很熟悉了,这里我们快速通过,本篇可能是最短的一篇。因为不打算细说,并且第十三章的内容本来也很少。 分两块,守护进程的结构,以及如何...

linux网络编程十一:将程序后台化,以守护进程的方式运行

1. 代码 #include #include #include #include #include #include #include bool daemonize() { ...

APUE函数笔记十五: 高级进程间通信(部分)

第十七章  高级进程间通信(部分): #include int fattach(int filedes, const char * path); if success return 0, ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:APUE函数笔记十一: 守护进程
举报原因:
原因补充:

(最多只允许输入30个字)