Unix/Linux编程-创建守护进程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/water_3700348/article/details/78372797

创建守护进程


#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);
	}
}


猜你喜欢

转载自blog.csdn.net/water_3700348/article/details/78372797