[DEMO] linux环境下将进程转为守护进程

前言:

守护进程脱离了前台控制终端,不会因为控制台的退出而退出,几乎所有的服务程序都是守护进程,但是把进程转换成是守护进程需要很多个步骤,非常繁琐,这里给出一个分装好的函数,调用即可把当前进程变成守护进程。

使用方法:

#include <unistd.h>
#include <stdlib.h>
void daemonize(const char* cmd);


int main()
{
	daemonize("main");
	while(1) sleep(1);
}

源码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <errno.h>

/*cmd填当前进程的进程名字符串,比如test,这个字符串会在openlog中,以在messages中标注是哪个程序输出了当前日志
 * */
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)
		{
			perror("can not get file limit.");
			exit(-1);
		}
	
	/*3-为了和当前终端tty脱离关系,把自己设置成为一个新会话的会话首进程,一个tty对应一个会话,
 	 *  因此这里设置会话就相当于和之前的会话脱离,即和tty脱离 
 	 *  下面这个fork的意义:只有非进程组组长才能成为会话首进程,这里fork一次以使子进程不可能成为
 	 *  进程组组长,为后面的setsid做准备
	 */
	pid=fork();
	if(pid<0)
		{
			perror("can not fork at setsid.");
			exit(-1);
		}
	if(pid>0)	
		{
			exit(0);	/*父进程退出*/
		}
	setsid();		/*子进程设置自己为新会话的会话首进程,这个动作有如下3个隐藏含义:
				*  1)成为会话首进程;2)成为进程组组长;3)脱离控制终端,不再被控制
				*/

	/*4-重设SIGHUP动作*/
	sa.sa_handler = SIG_IGN;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags=0;
	if(sigaction(SIGHUP,&sa,NULL)<0)
		{
			perror("can not ignore SIGHUP.");
			exit(-1);
		}
	if((pid=fork())<0)
		{
			perror("can not fork at ignore SIGHUP.");
			exit(-1);
		}
	else if(pid!=0)
		{
			exit(0);
		}


	/*5-切换当前工作目录为根目录,这样可以防止某个文件系统无法被卸载
 	 *  解释:从父进程继承过来的当前工作目录可能挂在某个文件系统上,又因为守护进程一般都是长时间运
 	 *  行,如果我想提前卸载某个文件系统,但是守护进程还在运行,这个时候就会提示无法卸载。	
 	 * */
	if(chdir("/")<0)
		{
			perror("obt can noe change directory to /.");
			exit(-1);
		}


	/*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-设置日志输出到系统日志中————>/var/log/messages*/
	openlog(cmd,LOG_CONS,LOG_DAEMON);
	if(fd0!=0||fd1!=1||fd2!=2){
		syslog(LOG_ERR,"unexected-obt file descriptors %d %d %d",fd0,fd1,fd2);
		exit(-1);
	}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值