int fork_daemon(bool nochdir, bool noclose, TokenPipeEnd& endpoint)
函数作用:
daemon()的自定义实现。这实现了与glibc相同的操作顺序。
打开子进程的管道,以便能够等待事件发生。
@returns 0 if successful, and in child process.
>0 if successful, and in parent process.
-1 in case of error (in parent process).
如果成功,端点将是从子进程到父进程的管道的一端,可与TokenWrite(在子级中)或TokenRead(在父级中)一起使用。
函数声明情况如下:
函数声明文件如下:
函数流程图如下:
函数逻辑顺序图如下:
函数原始代码如下:
int fork_daemon(bool nochdir, bool noclose, TokenPipeEnd& endpoint)
{
//带有子进程的通信管道
std::optional<TokenPipe> umbilical = TokenPipe::Make();
if (!umbilical) {
return -1; //管道或管道2出现故障。
}
int pid = fork();
if (pid < 0) {
return -1; // fork失败了。
}
if (pid != 0) {
//父进程读取结束,关闭写入结束。
endpoint = umbilical->TakeReadEnd();
umbilical->TakeWriteEnd().Close();
int status = endpoint.TokenRead();
if (status != 0) { //设置子进程时出错。
endpoint.Close();
return -1;
}
return pid;
}
//子进程获得写入端,关闭读取端。
endpoint = umbilical->TakeWriteEnd();
umbilical->TakeReadEnd().Close();
#if HAVE_DECL_SETSID
if (setsid() < 0) {
exit(1); //设置id失败。
}
#endif
if (!nochdir) {
if (chdir("/") != 0) {
exit(1); // chdir失败了。
}
}
if (!noclose) {
//打开/dev/null,并将其克隆到STDIN、STDOUT和STDERR中分离,从终端。
int fd = open("/dev/null", O_RDWR);
if (fd >= 0) {
bool err = dup2(fd, STDIN_FILENO) < 0 || dup2(fd, STDOUT_FILENO) < 0 || dup2(fd, STDERR_FILENO) < 0;
//如果fd<=2,则不要关闭,以在没有打开任何文件描述符,调用程序的情况尝试处理。
if (fd > 2) close(fd);
if (err) {
exit(1); // dup2 failed.
}
} else {
exit(1); // open /dev/null failed.
}
}
endpoint.TokenWrite(0); // Success
return 0;
}