编写守护进程程序时需遵循一些基本规则,以防止产生不必要的交互作用,下面先说明这些规则,然后给出一个按照这些规则编写的函数deamonize.
(1)首先,调用umask将文件创建屏蔽字设置为一个已知值(通常为0)。
(2)调用fork,然后是父进程exit。
(3)调用setsid创建一个新会话。
(4)将当前工作目录更改为根目录。
(5)关闭不需要的文件描述符。
(6)将文件描述符0,1,2指向 /dev/null
以下是一个记录日志的守护进程。
1 #include "apue.h" //详解见另一片文章
2 #include <syslog.h>
3 #include <fcntl.h>
4 #include <sys/resource.h>
5
6 void deamonze(const char *cmd)
7 {
8 int i,fd0,fd1,fd2;
9 pid_t pid;
10 struct rlimit rl;
11 struct sigaction sa;
12
13 //1、调用umask将文件模式创建屏蔽字设置为一个已知值(通常为0)
14 umask(0);
15 if(getrlimit(RLIMIT_NOFILE,&rl)<0) //获取文件描述符的数量
16 err_quit("%s:can't get file limit",cmd);
17
18 //2、使子进程成为会话的组长
19 if((pid = fork())<0) //调用fork,然后父进程退出
20 err_quit("%s:can't fork",cmd);
21 else if(pid!=0) //父进程
22 exit(0); //退出父进程
23 setsid(); //调用setsid创建一个新会话
24
25 //3、确保未来的打开不能分配控制终端
26 sa.sa_handler = SIG_IGN;
27 sigemptyset(&sa.sa_mask);
28 sa.sa_flags = 0;
29 if(sigaction(SIGHUP,&sa,NULL)<0)
30 err_quit("%s:can't fork",cmd);
31 else if(pid != 0)
32 exit(0);
33
34 //4、切换工作目录到到根目录,避免无法卸载可卸载设备
35 if(chdir("/")<0)
36 err_quit("%s:can't change directory to /",cmd);
37
38 //6、关闭所有打开的文件描述符
39 if(rl.rlim_max == RLIM_INFINTY)
40 rl.rlim_max = 1024;
41
42 for(i=0;i<rl.rlim_max;i++)
43 close(i);
44
45 //6、把文件描述符0,1,2绑定到 /dev/null
46 fd = open("/dev/null",O_RDWR);
47 fd1 = dup(0);
48 fd1 = dup(0);
49
50 //初始化日志文件
51 openlog(cmd,LOG_CONS,LOG_DEAMON);
52 if(fd1!=0||fd1!=1||fd2!=2)
53 {
54 syslog(LOG_ERR,"unexpected file descriptors %d %d %d",fd0,fd1,fd2);
55 exit(1);
56 }
57
58 }
来源:https://www.cnblogs.com/houjun/p/4860498.html