守护进程编程步骤
1. 创建子进程,父进程退出
•所有工作在子进程中进行
•形式上脱离了控制终端
2. 在子进程中创建新会话
•setsid()函数
•使子进程完全独立出来,脱离控制
3. 改变当前目录为根目录
•chdir()函数
•防止占用可卸载的文件系统
•也可以换成其它路径
4. 重设文件权限掩码
•umask()函数
•防止继承的文件创建屏蔽字拒绝某些权限
•增加守护进程灵活性
5. 关闭文件描述符
•继承的打开文件不会用到,浪费系统资源,无法卸载
•getdtablesize()
•返回所在进程的文件描述符表的项数,即该进程打开的文件数目
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <syslog.h>
int main() {
pid_t pid;
int i,fd;
char *buf="This is a daemon program.\n";
if ((pid = fork()) < 0) {
printf("fork error!");
exit(1);
}else if (pid > 0) { // 第一步,fork且退出父进程
exit(0);
}
openlog("daemon_syslog",LOG_PID, LOG_DAEMON);
if ((setsid()) < 0){ // 第二步,在子进程中创建新会话。
syslog(LOG_ERR, "%s\n", "setsid");
exit(1);
}
if ((chdir("/")) < 0) { // 第三步,设置工作目录为根
syslog(LOG_ERR, "%s\n", "chdir");
exit(1);
}
umask(0); // 第四步,设置权限掩码
for(i = 0 ;i < getdtablesize(); i++) //第五步,getdtablesize返回子进程文件描述符表的项数
close(i); // 关闭这些不将用到的文件描述符
syslog(LOG_INFO, "%d", getpid());
while (1) {// 死循环表征它将一直运行
// 以读写方式打开"/tmp/daemon.log",返回的文件描述符赋给fd
if ((fd = open("/tmp/daemon.log", O_CREAT|O_WRONLY|O_APPEND, 0600)) < 0) {
syslog(LOG_ERR, "Open file error!\n");
exit(1);
}
// 将buf写到fd中
write(fd, buf, strlen(buf) + 1);
close(fd);
sleep(10);
printf("Never output!\n");
}
closelog();
return 0;
}
因为stdout被关掉了,所以“Never ouput!”不会输出。
查看/tmp/daemon.log,说明该程序一直在运行
tail /tmp/daemon.log
查看系统日记,cat /var/log/syslog 可看到输出:
Jan 8 17:04:57 cxw-VM daemon_syslog[25393]: 25393