本章将说明守护进程结构,以及如何编写守护进程程序。
守护进程,也就是通常说的Daemon进程,是Unix中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。
编程规则
在编写守护进程程序时需遵循一些基本规则,以防止产生不必要的交互作用。下面将说明这些规则。
1.调用umask将文件模式创建屏蔽字设置为一个已知值(通常是0)
2.调用fork,然后使父进程exit,保证了子进程不是进程组的组长进程,是下面进行setsid调用的先决条件
3.调用setsid创建一个新会话。然后它会执行3个步骤:(a)成为新会话的首进程 (b)成为一个新进程组的组长进程 (c)没有控制终端
4.将当前工作目录更改为根目录。
5.关闭不再需要的文件描述符
6.某些守护进程打开/dev/null使其具有文件描述符0、1、2
下面函数演示了创建守护进程的基本步骤
1 #include "apue.h" 2 #include <syslog.h> 3 #include <fcntl.h> 4 #include <sys/resource.h> 5 6 void 7 daemonize(const char *cmd) 8 { 9 int i, fd0, fd1, fd2; 10 pid_t pid; 11 struct rlimit rl; 12 struct sigaction sa; 13 14 /* 15 * Clear file creation mask. 16 */ 17 umask(0); 18 19 /* 20 * Get maximum number of file descriptors. 21 */ 22 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) 23 err_quit("%s: can't get file limit", cmd); 24 25 /* 26 * Become a session leader to lose controlling TTY. 27 */ 28 if ((pid = fork()) < 0) 29 err_quit("%s: can't fork", cmd); 30 else if (pid != 0) /* parent */ 31 exit(0); 32 setsid(); 33 34 /* 35 * Ensure future opens won't allocate controlling TTYs. 36 */ 37 sa.sa_handler = SIG_IGN; 38 sigemptyset(&sa.sa_mask); 39 sa.sa_flags = 0; 40 if (sigaction(SIGHUP, &sa, NULL) < 0) 41 err_quit("%s: can't ignore SIGHUP", cmd); 42 if ((pid = fork()) < 0) 43 err_quit("%s: can't fork", cmd); 44 else if (pid != 0) /* parent */ 45 exit(0); 46 47 /* 48 * Change the current working directory to the root so 49 * we won't prevent file systems from being unmounted. 50 */ 51 if (chdir("/") < 0) 52 err_quit("%s: can't change directory to /", cmd); 53 54 /* 55 * Close all open file descriptors. 56 */ 57 if (rl.rlim_max == RLIM_INFINITY) 58 rl.rlim_max = 1024; 59 for (i = 0; i < rl.rlim_max; i++) 60 close(i); 61 62 /* 63 * Attach file descriptors 0, 1, and 2 to /dev/null. 64 */ 65 fd0 = open("/dev/null", O_RDWR); 66 fd1 = dup(0); 67 fd2 = dup(0); 68 69 /* 70 * Initialize the log file. 71 */ 72 openlog(cmd, LOG_CONS, LOG_DAEMON); 73 if (fd0 != 0 || fd1 != 1 || fd2 != 2) { 74 syslog(LOG_ERR, "unexpected file descriptors %d %d %d", 75 fd0, fd1, fd2); 76 exit(1); 77 } 78 }