デーモンプロセス起動時の作法
デーモンを起動する場合、2度forkするのが作法らしく、これは「セッションリーダにならないようにすることで端末の制御を誤ってしないように」ということらしい。
詳しくはこちらを参照
そうなのかぁと思いながら、見よう見まねでdaemonの関数を作ってみました。
サンプルプログラム
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> static pid_t do_daemon(int close_interface) { pid_t ret; int fd; /*create child process and terminate parent process*/ ret = fork(); if( ret < 0 ){ /* fork error */ perror("Cannot fork"); return(-1); }else if( ret != 0 ){ /* parent process */ return(ret); } /* child process */ /* change chiled process to session gruop reader */ ret = setsid(); if( ret < 0 ){ perror("Cannot create a session"); return(-1); } /* create 2nd child process and terminate parent process again * to never connect terminal */ ret = fork(); if( ret < 0 ){ /* fork error */ perror("Cannot fork"); return(-1); }else if( ret != 0 ){ /* parent process */ return(ret); } /* change the current directory to root directory */ (void) chdir("/"); /* close stdin/stdout/stderr */ fd = open("/dev/null", O_RDWR); if( fd < 0 ){ perror("Cannot open NULL device"); return(-1); } /* close the STDIN file descriptor */ if ((fd != STDIN_FILENO) && (dup2(fd, STDIN_FILENO) < 0)){ perror("Cannot close the STDIN"); (void)close(fd); return(-1); } /* close the STDOUT and STDERR file descriptor, if option is TRUE */ if( close_interface ){ /* close the STDOUT file descriptor */ if ((fd != STDOUT_FILENO) && (dup2(fd, STDOUT_FILENO) < 0)) { perror("Cannot close the STDOUT"); (void)close(fd); return(-1); } /* close the STDERR file descriptor */ if ((fd != STDERR_FILENO) && (dup2(fd, STDERR_FILENO) < 0)) { perror("Cannot close the STDERR"); (void)close(fd); return(-1); } } if( fd > STDERR_FILENO ){ (void)close(fd); } /* daemon complete */ return(0); }
でもudevとかsyslogdとかのソースを見ると、案外fork一度しかやってなかったりするんだけどね。