拾遗:Unix 守护进程编写规范

//标准库自带函数,通常以 daemon(0, 0) 方式调用
int daemon(int nochdir, int noclose)

Linux:
  #include <unistd.h>

FreeBSD:
  #include <stdlib.h>

//自主实现原理如下 

[a] 编写守护进程的要点

  • 指定 umask 值,由环境继承来的默认权限有可能存在问题
  • 使该守护进程成为一个孤儿进程组中的唯一成员:
    • fork 之后终止父进程,此举确保不是进程组首进程,然后 setsid 创建新会话
    • 丢弃会话首进程身份(再次 fork),从而确保了该进程不会获得控制终端
  • 切换到正确的工作目录中
  • 如果没有关联的配置文件,则可以设置 SIG_IGN 忽略 SIG_HUP 信号
  • 关闭不需要的文件描术符,可以将常用的 0、1、2 三个描述符关联至 /dev/null,以防止意外 I/O

[b] 样例

 1 #include <sys/types.h>
 2 #include <sys/time.h>
 3 #include <sys/stat.h>
 4 #include <sys/resource.h>
 5 #include <fcntl.h>
 6 #include <unistd.h>
 7 #include <stdio.h>
 8 #include <signal.h>
 9 
10 void daemonize(const char *);
11 char *workdir = "/";
12 
13 int
14 main(void)
15 {
16     daemonize(workdir);
17     while(1)
18     {
19         sleep(10);
20     }
21 }
22 
23 void
24 daemonize(const char *workdir)
25 {
26     pid_t pid;
27     int fd0, fd1, fd2;
28     struct rlimit rl;
29     struct sigaction sa;
30     
31     umask(0);
32     chdir(workdir);
33     
34     pid = fork();
35     if (pid < 0)
36     {
37         perror("fork");
38     }
39     else if (pid > 0)
40     {
41         _exit(0);
42     }
43     
44     setsid();
45     
46     pid = fork();
47     if (pid < 0)
48     {
49         perror("fork");
50     }
51     else if (pid > 0)
52     {
53         _exit(0);
54     }
55     
56     if (-1 == getrlimit(RLIMIT_NOFILE, &rl))
57     {
58         perror("getrlimit");
59     }
60     if (rl.rlim_max == RLIM_INFINITY)
61     {
62         rl.rlim_max = 1024;
63     }
64     for(pid = 0; pid < rl.rlim_max; ++pid)
65     {
66         close(pid);
67     }
68     
69     fd0 = open("/dev/null", O_RDWR);
70     fd1 = dup2(fd0, 1);
71     fd2 = dup2(fd0, 2);
72 
73     sa.sa_handler = SIG_IGN;
74     sa.sa_flags = 0;
75     sigemptyset(&sa.sa_mask);
76     if (sigaction(SIGHUP, &sa, NULL) < 0)
77     {
78         perror("sigaction");
79     }
80 }

...

原文地址:https://www.cnblogs.com/hadex/p/6206651.html