Ubuntu Linux 16.04 데몬 기능은 이중 포크를 수행합니까? 그렇다면 왜 이중 포크가 필요한가요?
[2016년 5월 30일 오전 8:11 수정됨] 이것은 제가 이 질문에서 언급한 데몬 기능에 대한 공식 Linux Foundation 소스 코드입니다.
92 int daemon(int nochdir, int noclose)
93 {
94 int status = 0;
95
96 openlog("daemonize", LOG_PID, LOG_DAEMON);
97
98 /* Fork once to go into the background. */
99 if((status = do_fork()) < 0 )
100 ;
101
102 /* Create new session */
103 else if(setsid() < 0) /* shouldn't fail */
104 status = -1;
105
106 /* Fork again to ensure that daemon never reacquires a control terminal. */
107 else if((status = do_fork()) < 0 )
108 ;
109
110 else
111 {
112 /* clear any inherited umask(2) value */
113
114 umask(0);
115
116 /* We're there. */
117
118 if(! nochdir)
119 {
120 /* Go to a neutral corner. */
121 chdir("/");
122 }
123
124 if(! noclose)
125 redirect_fds();
126 }
127
128 return status;
129 }
실행 경로에 따라 한 번 또는 두 번 분기됩니다.
답변1
daemon(3)
소스 코드가 #1에 있을 수 있는 라이브러리 호출을 참조하고 있는 것 같습니다 .https://github.com/lattera/glibc/blob/master/misc/daemon.c아니면 #2에서https://github.com/bmc/daemonize/blob/master/daemon.c. 두 버전 모두 이번 싱글에 녹음되었습니다.매뉴얼 페이지.
#1의 소스 코드는 를 보여줍니다 fork(2)
. #2의 소스 코드는 double 을 보여줍니다 fork(2)
. 표면적으로 이 두 함수는 동일한 결과를 제공하는 것처럼 보이지만 방식은 다릅니다.
이중으로 취급하는 것이 fork(2)
항상 필요한 것은 아닙니다. 이는 질문의 두 번째 부분의 추진력에 어긋나서 더 이상 필요하지 않다고 생각합니다. 그러나 이 접근 방식의 근본적인 이유는 포크된 프로세스가 어떤 상황에서도 제어 터미널을 다시 획득할 수 없도록 보장하는 것입니다. 최신 코드에서는 하위 프로세스를 새 세션 리더로 설정하여 이 문제를 해결합니다.
이 사이트와 비슷한 질문을 하는 다른 StackOverflow 사이트에 다른 관련 질문이 있습니다. 이것은하나.
답변2
다음 과 같이 포크 glibc
만daemon()
소스 코드.
처음에는 외부에서 직접 참조하는 대신 커널의 소스 코드를 살펴봅니다.
이중 포크의 사용은 실제 호출 데몬의 구현에 따라 달라지며 데몬이 일반 세션에서 시작되지 않기 때문에 대부분의 디자인에서는 필요하지 않습니다.
커널 소스 코드에서 볼 수 있듯이 두 번 분기하면 부모 프로세스가 첫 번째 프로세스에 있었기 때문에 프로세스가 부모에서 완전히 분리됩니다 fork()
. 두 번째 프로세스를 호출 fork()
하고 부모를 죽이면 프로세스가 할당됩니다. 이 역시 완전히 제거됩니다. (상위 프로세스 ID) 1
에 PPID
할당된 TTY입니다 .