Linux下守护进程精析

什么是守护进程?
    守护进程就是通常所说的Daemon进程,它是Linux中的后台服务程序。

它是一个生存期较长的进程,通常独立于终端而且周期性的运行某种须要的任务以及有时候会等待一些将会发生的事情。守护进程经常会在系统启动的时候開始运行,在系统关闭的时候关闭,它实现了linux系统中的非常多系统级的服务。

    还有一方面Daemon不受终端的影响,不会由于某个终端的关闭而关闭。所以,假设你希望你的进程不会由于用户或者终端的变化而变化。那么你就必需要知道怎么把你的进程设置为守护进程(也就是所说的Daemon进程了)。

编写守护进程事实上没有看似那么的复杂,就是完毕下面五步骤就可以创建出一个Daemon进程,
创建守护进程的5个步骤:

(1)创建子进程,父进程退出  。

这一步就是要在外表看来让子进程与终端脱离。这个时候原先的子进程就会变为孤儿进程,那么孤儿进程就会被init进程进行收养了。


(2)在子进程中创建的新会话setsid() : 调用者不能是组长进程],这一步是创建守护进程最重要的一步了,尽管实现很大的简单。可是意义很的重大。

先介绍下setsid()函数的作用:

    setsid()函数用于创建一个新的会话,并担任该会话组的组长,调用setsid()有以下3个作用:
    (1)让进程拜托原会话的控制
    (2)让进程拜托原进程组的控制
    (3)让进程拜托原控制终端的控制
    那么接下来我们就会非常清楚的知道我们为什么要去运行setsid()函数了,由于在第一步我们创建进程的时候。子进程全盘复制了父进程的会话期,进程组,和控制终端等。

尽管父进程退出了。但原先的会话期。进程组和控制终端没有变。因此还不是真正意义上的独立了。而setsid()函数可以让进程全然的独立出来,从而脱离全部其他进程的控制哦。


(3)改变进程的工作文件夹到"/" ; 改变工作文件夹的函数时chdir();

(4)重设文件掩码,通常使用的方法是 umask(0) ; 文件权限掩码(通经常使用8进制表示)的作用是屏蔽文件权限中的相应位。 

(5)关闭不须要的文件描写叙述符号 。通常关闭的是[0,1,2,3]   
    同文件权限掩码一样。用fork()函数新建的子进程会从父进程那里继承一些已经打开了的文件。这些被打开的文件可能永远不会被守护进程訪问。但它们一样占用系统资源,并且还可能导致所在的文件系统无法被卸载。

特别是守护进程和终端无关,所以指向终端设备的标准输入,标准输出和标准错误流,已经失去了存在的价值。应当被关闭。通常的做法例如以下:

        int  num;
        num  =  getdtablesize(); //获取当前进程文件描写叙述符表的大小
        for(i = 0;i < num ;i++)
        {    
            close( i );
        }


    经过上述的五大步骤。一个简单的守护进程就建立起来了。

大致的流程见下图:



 

好了。大致的思想了解之后,接下来的事情就简单的多了,无非就是代码的实现的问题了;

以下以守护进程为出发点列举一个样例,希望能够具体的了解下,看看守护进程是怎样实现时间日志


#include <head.h>

#define daemo_mode 0
#define nomal_mode 1

int  daemo() //5步创建守护进程
{
	pid_t pid;
	pid = fork();
	if(pid < 0)
	{
		fprintf(stderr,"File to fork
",strerror(errno));
		exit(EXIT_FAILURE);
	}
	if(pid > 0)
		exit(EXIT_FAILURE);
	
	if(setsid() < 0)
	{
		perror("File to setsid");
		exit(EXIT_FAILURE);
	}
	chdir("/");
	umask(0);
	close(0);
	close(1);
	close(2);
	return 0;
}

int get_line(FILE *fp)
{
	int line;
	char *tmp;
	char buf[4096];
	while(1)
	{
		tmp = fgets(buf,sizeof(buf),fp);
		if(tmp == NULL)
			break;
		if(buf[strlen(tmp) - 1] == '
')
			line++;
	}
	return line;
}

int do_nomal(const char *filename)
{
	FILE * fp;
	time_t t;
	struct tm *ptm;
	int line = 0;

	fp = fopen(filename,"a+");

	if(fp == NULL)
	{
		fprintf(stderr,"File to fopen
",strerror(errno));
		exit(EXIT_FAILURE);
	}

	line = get_line(fp);

	while(1)
	{
		++line;
		time(&t); //The realization of time
		ptm = localtime(&t);

		sleep(1);
		fflush(fp);
		fprintf(fp,"%d-%d-%d",(1900+ptm->tm_year),(1+ptm->tm_mon),ptm->tm_mday);
		fprintf(fp,"%d:%d:%d
",ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
	}
	return 0;
}
// ./a.out log 0/1
int main(int argc, const char *argv[])
{
	if(argc < 3)
	{
		fprintf(stderr,"Usage : %s argv[1] argv[2]
",argv[0]);
		exit(EXIT_FAILURE);
	}
	int mode = atoi(argv[2]);
	switch(mode)
	{
	case daemo_mode:
		daemo();
		break;
	case nomal_mode:
		break;
	default:
		printf("Unknow mode 
");
		goto next;
	}
	do_nomal(argv[1]);

next:
	return 0;
}



原文地址:https://www.cnblogs.com/yjbjingcha/p/6973893.html