编写一个守护进程

 编写守护进程程序时需遵循一些基本规则,以防止产生不必要的交互作用,下面先说明这些规则,然后给出一个按照这些规则编写的函数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 }

 

posted @ 2015-10-08 11:35  HOU_JUN  阅读(523)  评论(0编辑  收藏  举报