Linux守护进程
redis版:
void daemonize(void) { int fd; if (fork() != 0) exit(0); /* parent exits */ setsid(); /* create a new session */ /* Every output goes to /dev/null. If Redis is daemonized but * the 'logfile' is set to 'stdout' in the configuration file * it will not log at all. */ if ((fd = open("/dev/null", O_RDWR, 0)) != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > STDERR_FILENO) close(fd); } }
memcached版:
int daemonize(int nochdir, int noclose) { int fd; switch (fork()) { case -1: return (-1); case 0: break; default: _exit(EXIT_SUCCESS); } if (setsid() == -1) return (-1); if (nochdir == 0) { if(chdir("/") != 0) { perror("chdir"); return (-1); } } if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) { if(dup2(fd, STDIN_FILENO) < 0) { perror("dup2 stdin"); return (-1); } if(dup2(fd, STDOUT_FILENO) < 0) { perror("dup2 stdout"); return (-1); } if(dup2(fd, STDERR_FILENO) < 0) { perror("dup2 stderr"); return (-1); } if (fd > STDERR_FILENO) { if(close(fd) < 0) { perror("close"); return (-1); } } } return (0); }
lighttpd版:
#ifdef HAVE_FORK static void daemonize(void) { #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif if (0 != fork()) exit(0); if (-1 == setsid()) exit(0); signal(SIGHUP, SIG_IGN); if (0 != fork()) exit(0); if (0 != chdir("/")) exit(0); } #endif
ngx_int_t ngx_daemon(ngx_log_t *log) { int fd; switch (fork()) { case -1: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed"); return NGX_ERROR; case 0: break; default: exit(0); } ngx_pid = ngx_getpid(); if (setsid() == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed"); return NGX_ERROR; } umask(0); fd = open("/dev/null", O_RDWR); if (fd == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(\"/dev/null\") failed"); return NGX_ERROR; } if (dup2(fd, STDIN_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed"); return NGX_ERROR; } if (dup2(fd, STDOUT_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed"); return NGX_ERROR; } #if 0 if (dup2(fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed"); return NGX_ERROR; } #endif if (fd > STDERR_FILENO) { if (close(fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed"); return NGX_ERROR; } } return NGX_OK; }
注释版:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> int daemonize(void) { int fd; switch(fork()) { case -1: return (-1); case 0: break; default: //将父进程结束,让子进程变成真正的孤儿进程,并被init进程接管 exit(0); } //子进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离 setsid(); if ((fd = open("daemon.log", O_CREAT|O_RDWR|O_APPEND, 0)) != -1) { //dup2(int oldhandle, int newhandle)复制文件句柄 dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); //0,1和2文件句柄分别与标准输入,标准输出,标准错误输出相关联 //所以用户应用程序调用open函数打开文件时,默认都是以3索引为开始句柄 //fd已经由新的句柄代替,关闭fd句柄 if (fd > STDERR_FILENO) (void)close(fd); } return 0; } int main(int argc, char *argv[]) { daemonize(); printf("%s\n","hello"); return 0; }
# cc daemonize.c -o daemonize
# ./daemonize
# ps aux | grep daemonize
参考:
http://blog.linuxphp.org/archives/1476/
http://www.cnblogs.com/xuxm2007/archive/2011/07/29/2121280.html
http://blog.csdn.net/yyyzlf/article/details/5267954
http://docs.linuxtone.org/ebooks/C&CPP/c/ch34s03.html