将进程转换为守护进程
/* 将进程变为守护进程 */
static int daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit r1;
struct sigaction sa;
/* Clear file creation mask. */
umask(0);
/* Get maximum number of file descriptors */
if (getrlimit(RLIMIT_NOFILE, &r1) < 0){
bbr_log_err("[%s][%s][%d]%s: can't get file limit\n", __FILE__, __func__, __LINE__, cmd);
return -1;
}
/* Become a session leader to lose controlling TTY */
if ((pid = fork()) < 0){
bbr_log_err("[%s][%s][%d]can't fork\n",__FILE__, __func__, __LINE__);
return -1;
} else if (pid != 0) /* parent */
exit(0); // parent terminates
// child 1 continues...
if (setsid() < 0){// become session leader
bbr_log_err("[%s][%s][%d]setsid failed\n",__FILE__, __func__, __LINE__);
return -1;
}
/* Ensure future opens won't allocate controlling TTYs */
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0){
bbr_log_err("[%s][%s][%d]can't ignore SIGHUP\n",__FILE__, __func__, __LINE__);
return -1;
}
if ((pid = fork()) < 0){
bbr_log_err("[%s][%s][%d]can't fork\n",__FILE__, __func__, __LINE__);
return -1;
} else if (pid != 0) // parent
exit(0); // child 1 terminates
//child 2 continues...
/* Change the current working directory to the root so
* we won't prevent file systems from being unmounted.
* */
// change working directory
if (chdir("/") < 0){
bbr_log_err("[%s][%s][%d]can't change directory to /\n",__FILE__, __func__, __LINE__);
return -1;
}
/* Close all open file descriptors. */
if (r1.rlim_max == RLIM_INFINITY)
r1.rlim_max = 1024;
for (i = 0; i < r1.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);
if (fd0 != 0 || fd1 != 1 || fd2 != 2){
bbr_log_err("[%s][%s][%d]unexpected file descriptors %d %d %d\n",__FILE__, __func__, __LINE__, fd0, fd1, fd2);
return -1;
}
return 0; /* success */
}