home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/UNIX/daemon習作

技術/UNIX/daemon習作

技術 / UNIX / daemon習作
id: 857 所有者: msakamoto-sf    作成日: 2010-12-02 12:46:15
カテゴリ: C言語 Linux UNIX 

fork(), setsid(), ファイル記述子のclose()などを処理するdaemonize()関数を使った、daemon習作。
単にログファイルにPIDとかPGIDをprintf()し続けるだけ。

参考:APUE, Chapter13, Daemon Processes

ヘッダーのとりまとめやエラー処理は 技術/UNIX/libtinyaup を流用。

daemon01.c:

#include "libtinyaup.h"
#include <termios.h>
#include <syslog.h>
 
void
print_mes(FILE *fp)
{
    static int cnt = 0;
    int i;
    char *buf;
    pid_t pid;
    fprintf(fp, "============== [%d]\n", cnt);
 
    fprintf(fp, "RUID=[%d],EUID=[%d],RGID=[%d],EGID=[%d]\n",
        getuid(), geteuid(), getgid(), getegid());
    fprintf(fp, "PID=[%d], PPID=[%d], PGRP=[%d], SID=[%d]\n",
        getpid(), getppid(), getpgrp(), getsid(getpid()));
    for (i = 0; i < 3; i++) {
        if (-1 != (pid = tcgetsid(i))) {
            fprintf(fp, "SID[%d]=%d\n", i, pid);
        } else {
            fprintf(fp, "SID[%d]=err:%s\n", i, strerror(errno));
        }
    }
    for (i = 0; i < 3; i++) {
        buf = ttyname(i);
        if (NULL == buf) {
            buf = strerror(errno);
        }
        fprintf(fp, "ttyname[%d]='%s'\n", i, buf);
    }
 
    fflush(fp);
    cnt++;
}
 
void
proc_daemon(const char *cmd, const char *mylog)
{
    FILE *fp = NULL;
    int i;
    openlog(cmd, LOG_PID, LOG_LOCAL0);
    syslog(LOG_DEBUG, "starting %s...", cmd);
    if (NULL == (fp = fopen(mylog, "w"))) {
        syslog(LOG_ERR, "fopen(%s) failed, %d, %m", mylog, errno);
        exit(1);
    }
    for (i = 0;; i++) {
        print_mes(fp);
        syslog(LOG_DEBUG, "message written to %s (%d)", mylog, i);
        sleep(3);
    }
}
 
void
daemonize(void)
{
    int i, fd0, fd1, fd2;
    pid_t pid;
    struct rlimit rl;
    struct sigaction sa;
 
    /* clear file creation mask */
    umask(0);
 
    /* get maximum number of file descriptors */
    ec_neg1(getrlimit(RLIMIT_NOFILE, &rl));
 
    /* become a session leader to lose controlling tty */
    ec_neg1(pid = fork());
    if (0 != pid) exit(0); /* parent exit */
 
    /* child...*/
    setsid();
 
    /* ensure future opens won't allocate controlling TTYs (SysV) */
    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    ec_neg1(sigaction(SIGHUP, &sa, NULL));
    ec_neg1(pid = fork());
    if (0 != pid) exit(0); /* parent exit */
 
    /* change to root directory */
    ec_neg1(chdir("/"));
 
    /* close all open file descriptors */
    if (RLIM_INFINITY == rl.rlim_max) {
        rl.rlim_max = 1024;
    }
    for (i = 0; i < rl.rlim_max; i++) {
        close(i);
    }
 
    /* attach file descriptors 0, 1, and 2 to /dev/null */
    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);
 
    return;
 
EC_CLEANUP_BGN
    exit(127);
EC_CLEANUP_END
}
 
int main(int argc, char *argv[])
{
    if (2 > argc) {
        fprintf(stderr, "usage: %s logfile\n", argv[0]);
        return 1;
    }
    print_mes(stdout);
    printf("hit return then start daemon:");
    getchar();
    printf("starting daemon...\n");
    print_mes(stdout);
 
    daemonize();
 
    proc_daemon(argv[0], argv[1]);
 
    return 0;
}

Makefile(sample):

LIBTINYAUP_DIR=/opt/SVNWORK/libtinyaup
LIBTINYAUP_OS=LINUX

EXTRA=
EXTRALIBS=

CC=gcc
CFLAGS=-D$(LIBTINYAUP_OS) -D_GNU_SOURCE -D_REENTRANT -D_THREAD_SAFE -ansi -std=c99 \
        -I$(LIBTINYAUP_DIR) -Wall -Wimplicit -Wstrict-prototypes $(EXTRA)
COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c

LDDIR=-L$(LIBTINYAUP_DIR)
LDLIBS=$(LIBTINYAUP_DIR)/libtinyaup.a $(EXTRALIBS)
LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDDIR) $(LDFLAGS)

TEMPFILES=core core.* *.o temp.* *.out

PROGS = daemon01

all:    ${PROGS}

clean:
        rm -f ${PROGS} ${TEMPFILES}

実際はdaemontoolsなどを活用すべきだろう。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2010-12-02 12:53:58
md5:72f3a9256831ef2fa6119db8c57c0ffb
sha1:413627b2e83ebec4791bef13a8750805f7668739
コメント
コメントを投稿するにはログインして下さい。