Here's how Stevens thinks you should demonize:
void daemonize(const char *cmd) {
if ((pid = fork()) < 0)
err(1, "fork fail");
else if (pid != 0) /* parent */
exit(0)
/* child A */
setsid()
if ((pid = fork()) < 0)
err(2, "fork fail");
else if (pid != 0) /* child A * /
exit(0)
/* child B (grandchild) */
do_daemon_stuff();
}
Most people have two questions about this code:
Why
setsid()
is it in the first child?
Why do
fork()
it again?
Why is setsid () in the first child?
According to Stevens, setsid()
it does three important things:
The process becomes the session leader of the new session, which contains only the calling process. (PID = SID)
. (PID = SID = PGID)
.
setsid()
, .
, setsid()
, (PID = PGID), fork()
, , ( ).
setsid()
, . , , .
fork() ?
:
,
init
, . Unix ,fork()
. , , ,init
, ,waitpid()
,fork()
.fork()
waitpid()
, . , , , -init
, ,init
SIGCLD, ,init
waitpid()
.
System V
fork()
- . System V: AIX, Solaris HP-UX,fork()
, .
?
, , wait/waitpid()
, ( - !). wait/waitpid()
pid
, . .
, - . , busybox - 2005 , - , init
. , , waitpid
, .
:
,
,
wait/waitpid
, , , :
kernel reaper , SIGCHLD (OpenBSD).
exit()
, SIGCHLD, , (XNU/OSX)
, . SIGCHLD, fork
setsid
. SIGCHLD, , wait
.
static void signal_handler(int sig) {
int stat;
wait(&stat);
}
void main(void) {
struct sigaction sigact;
sigact.sa_handler = signal_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGCHLD, &sigact, (struct sigaction *)NULL);
if ((pid = fork()) < 0)
err(1, "fork fail");
else if (pid != 0)
do_parent_stuff();
else {
setsid()
do_child_stuff();
}
}
« C».
- « C Windows». C Windows, exe-. " " .
- « C».