创建守护进程
#include <fcntl.h>
#include <sys/resource.h>
#include <syslog.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
// 守护进程通过 syslog 输出的日志信息记录在 /var/log/syslog 日志文件中
// 创建守护进程
void daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
// 1. 清除创建文件掩码
umask(0);
// 2. 获取最大文件描述符
if(getrlimit(RLIMIT_NOFILE, &rl) < 0)
{
printf("%s: cannot get file limit\n", cmd);
return;
}
// 3. 成为脱离控制终端的会话组长
if((pid = fork()) < 0)
{
printf("%s: cannot fork\n", cmd);
return;
}
else if(pid != 0) // 父进程退出
{
exit(0);
}
setsid();
// 4. 确保将来启动守护进程不会分配控制终端
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if(sigaction(SIGHUP, &sa, NULL) < 0)
{
printf("%s: cannot ignore SIGHUP\n", cmd);
return;
}
// 再次产生子进程,使其不会成为会话首进程,防止取得控制终端
if((pid = fork()) < 0)
{
printf("%s: cannot fork", cmd);
return;
}
else if(pid != 0) // 父进程退出
{
exit(0);
}
// 5. 工作目录切换为根目录,这样防止文件系统被卸载
if(chdir("/") < 0)
{
printf("%s: cannot change directory to /", cmd);
return;
}
// 6. 关闭所有打开的文件
if(rl.rlim_max == RLIM_INFINITY)
{
rl.rlim_max = 1024;
}
for(i = 0; i < rl.rlim_max; i++)
{
close(i);
}
// 7. 将文件描述符0,1,2指向 /dev/null
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
// 8. 初始化日志文件
openlog(cmd, LOG_CONS, LOG_DAEMON);
if(fd0 != 0 || fd1 != 1 || fd2 != 2)
{
syslog(LOG_ERR, "unexcepted file descriptor %d %d %d", fd0, fd1, fd2);
exit(1);
}
// 以上是使进程成为守护进程
// 以下的工作才是这守护进程要做的工作
i = 1;
while (1)
{
syslog(LOG_INFO, "test - %d\n", i++);
sleep(2);
}
}