1. 编程规则
i. 调用umask将文件模式创建屏蔽字设置为一个已知值;
ii. 调用fork,然后使父进程exit;
iii. 调用setsid创建一个新会话;
iX. 将当前工作目录更改为根目录;
X. 关闭不需要的文件描述符;
Xi. 某些守护进程打开/dev/null使其具有文件描述符0,1,2,这样,任何一个试图读标准输入,写标准输出或标准错误的库例程都不会产生任何的效果。
<span style="font-size:18px;">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 maxinum number of file descriptors
if(getrlimit(RLIMIT_NOFILE, &rl) < 0)
err_quit("%s: can't get file limit", cmd);
//Become a session leader to lose controlling TTY
if((pid = fork()) < 0)
err_quit("%s: can't fork", cmd);
else if(pid != 0)
exit(0);
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)
err_quit("%s: can't ignore SIGHUO", cmd);
else if(pid != 0)
exit(0);
//Change the current working directory to the root
//So we won't prevent file systems from being unmouted
if(chdir("/") < 0)
err_quit("%s: can't change directory to /", cmd);
//Clost 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 ro /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);
}
} </span>
2. 出错记录
有3种产生日志消息的方法
i. 内核例程可以调用log函数
ii. 大多数用户进程(守护进程)调用syslog(3)函数来产生日志消息。
iii. 无论一个用户进程是在此主机上,还是通过TCP/IP网络连接到此主机的其他主机上,都可将日志消息发向UDP端口514。
守护进程在启动时读一个配置文件,文件名一般为/etc/syslog.conf,该文件决定了不同种类的消息应送向何处。
void openlog(const char* ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
int setlogmask(int maskpri);
3. 单实例守护进程
4. 守护进程的惯例
i. 若守护进程使用锁文件,那么该文件通常存储在/var/run目录中,锁文件名字通常是name.pid
ii. 若守护进程支持配置选项,那么配置文件通常存放在/etc目录中。 配置文件的名字通常是name.conf
iii. 守护进程是可用命令行启动,但通常它们是系统初始化脚本之一
iX. 若一个守护进程有一个配置文件,那么当该守护进程启动时会读该文件,但在此之后一般就不会查看它。
5. 客户进程-服务器进程模型