#navi_header|技術| fork(), setsid(), ファイル記述子のclose()などを処理するdaemonize()関数を使った、daemon習作。 単にログファイルにPIDとかPGIDをprintf()し続けるだけ。 参考:APUE, Chapter13, Daemon Processes #more|| ヘッダーのとりまとめやエラー処理は [[844]] を流用。 daemon01.c: #code|c|> #include "libtinyaup.h" #include #include 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): #pre||> 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などを活用すべきだろう。 #navi_footer|技術|