下面的代码给出了如何创建一个守护进程。
这个是没有sleep的结果
$./daemon
father : pid = 22957, ppid = 10927, pgrp = 22957, sid = 10927, tpgrp = 22957
child before setsid : pid = 22958, ppid = 22957, pgrp = 22957, sid = 10927 , tpgrp = 22957
child after setsid : pid = 22958 , ppid = 22957, pgrp = 22958, sid = 22958 , tpgrp = -1
grand son : pid = 22959, ppid = 22958, pgrp = 22958, sid = 22958, tpgrp = -1
下面是sleep的结果
$./daemon
father : pid = 22978, ppid = 10927, pgrp = 22978, sid = 10927, tpgrp = 22978
child before setsid : pid = 22979, ppid = 1, pgrp = 22978, sid = 10927, tpgrp = 10927
child after setsid : pid = 22979, ppid = 1, pgrp = 22979, sid = 22979, tpgrp = -1
grand son : pid = 22980, ppid = 22979, pgrp = 22979, sid = 22979, tpgrp = -1
1. 可以看出setsid后,sid变成了当前进程的pid。
2. setsid后,tpgrp已经是-1,表示没有controlling terminal 了
#include <syslog.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
static void pr_ids(char *name)
{
printf("%-20s: pid = %d, ppid = %d, pgrp = %d, sid = %d, tpgrp = %d/n",
name , getpid(), getppid(), getpgrp(), getsid(0), tcgetpgrp(STDIN_FILENO));
fflush(stdout);
}
void
daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
/*
* Clear file creation mask.
*/
umask(0);
/*
* Get maximum number of file descriptors.
*/
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
printf("%s: can't get file limit", cmd);
pr_ids("father");
/*
* Become a session leader to lose controlling TTY.
*/
if ((pid = fork()) < 0)
printf("%s: can't fork", cmd);
else if (pid != 0) /* parent */
exit(0);
sleep(1);
pr_ids("child before setsid");
setsid ();
pr_ids("child after setsid");
/*
* 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)
printf("%s: can't ignore SIGHUP");
if ((pid = fork()) < 0)
printf("%s: can't fork", cmd);
else if (pid != 0) /* parent */
exit(0);
pr_ids("grand son ");
/*
* Change the current working directory to the root so
* we won't prevent file systems from being unmounted .
*/
if (chdir("/") < 0)
printf("%s: can't change directory to /");
/*
* Close all open file descriptors.
*/
if (rl.rlim_max == RLIM_INFINITY)
rl.rlim_max = 1024;
for (i = 0; i < rl.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);
/*
* Initialize the log file.
*/
openlog(cmd, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
syslog(LOG_ERR, "unexpected file descriptors %d %d %d",
fd0, fd1, fd2);
exit(1);
}
}
int main()
{
daemonize("test");
printf("life/n");
return 0;
}