《Unix环境高级编程》学习之编写守护进程

编写规则:

1、调用umask将文件模式创建屏蔽字置为一个已知值(通常是0),因为屏蔽字会阻碍某些权限,影响保护进程的执行;

2、调用fork,然后父进程exit,保证当前进程不是进程组组长;

3、调用setsid,创建一个新的会话;

4、再次调用fork,退出父进程,保证守护进程不是会话首进程,这样调用open重定向标准输入、标准输出、标准错误时,就不会被分配终端;

5、将当前工作目录更改为根目录(并非必须的),因为如果守护进程工作的目录挂载在一个文件系统中,那么该文件系统无法卸载;

6、关闭不需要的文件描述符;

7、重定向标准输入、标准输出、标准错误至/dev/null。


接下来是《Unix环境高级编程》中的一个例子:

#include "apue.h"
#include <syslog.h>
#include <fcntl.h>
#include <sys/resource.h>

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 maximum number of file descriptors.
	 */
	if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
	{
		err_quit("%s: can't get file limit", cmd);
	}

	/*
	 这一步fork保证进程不是进程组组长进程
	 */
	if ((pid = fork()) < 0)
	{
		err_quit("%s: can't fork", cmd);
	}
	else if (pid != 0) /* parent */
	{
		exit(0);
	}

	/*
	创建一个回话,会话只包含子进程,且子进程是会话首进程
	*/
	setsid();

	/*
	会话首进程的退出会出发SIGHUP信号
	默认此信号的操作会终止进程
	 */
	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 SIGHUP", cmd);
	}

	/*
	再次创建子进程,退出父进程,保证守护进程不是会话首进程,这样open的时候就不会被分配终端
	*/
	if ((pid = fork()) < 0)
	{
		err_quit("%s: can't fork", cmd);
	}
	else if (pid != 0) /* parent */
	{
		exit(0);
	}

	/*
	 * Change the current working directory to the root so
	 * we won't prevent file systems from being unmounted.
	 */
	if (chdir("/") < 0)
	{
		err_quit("%s: can't change directory to /", cmd);
	}

	/*
	 * Close all open file descriptors.
	 */
	if (rl.rlim_max == RLIM_INFINITY)
	{
		rl.rlim_max = 1024;
	}
	for (i = 0; i < rl.rlim_max; i++)
	{
		close(i);
	}

	/*
	 因为前面关闭了所有的文件描述符,此时open返回的必定是最小的0,后面两次dup返回的依次是1、2,也就完成了对标准输入、标准输出、标准错误重定向至/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);
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值