Linux应用程序设计-守护进程_07

守护进程

守护进程(Daemon)是Linux三种进程类型之一,称为精灵进程,是运行在后台的一种特殊进程;它独立于控制终端并且周期性地执行某种任务或等待处理发生的事件。 通常在系统启动时运行,系统关闭时结束**;守护进程不受用户登陆与注销的影响,它一直在运行着**。Linux系统中大量使用,很多服务程序以守护进程形式运行

转载这位博主的文章,感谢分享

https://blog.csdn.net/xiaodu655/article/details/80503712

利用ps -axj | more 查看所有用户的作业。

.ps:表示对进程监测和控制。
参数a:表示不仅列出当前用户的进程,也列出所有其他用户的进程;
数a:表示不仅列出当前用户的进程,也列出所有其他用户的进程。
参数x:表示不仅列出控制终端的进程,也列出所有无控制终端的进程。
参数j:表示列出与作业控制相关的信息。

Linux应用程序设计-守护进程_07
后台进程与守护进程的区别:
后台进程受用户登陆、注销的影响,依旧是该会话内部的进程。

守护进程特点

始终在后台运行;
独立于任何终端;
周期性的执行某种任务或等待处理特定事件;

会话、控制终端

Linux以会话(session)、进程组的方式管理进程

每个进程属于一个进程组

会话是一个或多个进程组的集合。通常用户打开一个终端时,系统会创建一个会话。所有通过该终端运行的进 程都属于这个会话

终端关闭时,所有相关进程会被结束

守护进程创建步骤:

Linux应用程序设计-守护进程_07

Step1: 创建子进程,父进程退出

pid = fork();
if( pid > 0 )
{
	exit(0);//父进程退出
}

子进程变成孤儿进程,被init进程收养
子进程在后台运行

Step2: 在子进程中创建新会话

 if (setsid() < 0) 
 {
        exit(-1);
}

子进程成为新的会话组长
子进程脱离原先的终端

进程组:是一个或多个进程的集合
会话期:是一个或多个进程组的集合,开始于用户登录,终止于用户退出;或者说开始于终端打开,结束于终端关闭。在此期间该用户运行的所有进程头属于这个会话期。

Linux应用程序设计-守护进程_07
setsid()函数作用:用于创建一个新的会话,并担任该会话的组长。调用setsid()有下面三个作用

  1. 让进程摆脱原会话的控制
  2. 让进程摆脱原进程组的控制
  3. 让进程摆脱原控制终端的控制

setsid()函数语法:

头文件 #include <unistd.h>
#include <sys/types.h>
函数原型 pid_t setsid(void);
函数返回值 成功:该进程的ID
出错: -1

Step3: 更改当前目录

chdir(“/”);
chdir(“/tmp”);

守护进程一直在后台运行,其工作目录不能被卸载
重新设定当前工作目录cwd

Step4: 重设文件权限掩码

通常的使用方法为 umask(0)

if (umask(0) < 0) 
{
        exit(-1);
}

Step5: 关闭文件描述符

守护进程和终端无关,所有指向终端设备的的标准输入、标准输出和标准错误流已经失去了存在的价值,应当被关闭。
int i;
for(i=0; i<getdtablesize(); i++)
{
close(i);
}
关闭所有从父进程继承的打开文件
已脱离终端,stdin / stdout / stderr无法再使用

守护进程每隔2秒 向日志文件中写入数据

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>


	

#if 1
int main(int argc, const char *argv[])
{
	pid_t pid;
	
	// Step1
	pid = fork();
	if( pid < 0 )
	{
		printf(" Error fork\n");
		exit(1);
	}
	else if (pid > 0)
	{
		//父进程退出 
		exit(0);
	}
	
	//Step2
	setsid();

	//Step3:
	chdir("/tmp");

	//Step4
	umask(0);

	//Step5
	int i;
	for(i=0; i< getdtablesize(); i++)
	{
		close(i);
	}
	
	//这时创建完守护进程,下面开始进入守护进程工作
	char buf[64] = "This is a Daemon1\n";
	int fp;

	while(1)
	{
#if 1
		if((fp = open("daemon.txt",O_WRONLY | O_CREAT | O_APPEND, 0600)) < 0 )
		{
			printf(" fail open \n");
			exit(1);
		}
#endif

		write(fp, buf, strlen(buf));
		
		close(fp);
		
		sleep(20);
	}
	exit(0);
}
#endif

/**************************************************************************************************************************************/

守护进程的一个程序模板:
#include <unistd.h>
#include <sys/stat.h>
#include <syslog.h>
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/file.h>
#include <stdio.h>
#include <sys/resource.h>
#include <signal.h>

int main(void)
{
	pid_t a;
	int max_fd, i;

	/*********************************************
	1. ignore the signal SIGHUP, prevent the
	   process from being killed by the shutdown
	   of the present controlling termination
	**********************************************/
	signal(SIGHUP, SIG_IGN);

	/***************************************
	2. generate a child process, to ensure
	   successfully calling setsid()
	****************************************/
	a = fork();
	if(a > 0)
		exit(0);

	/******************************************************
	3. call setsid(), let the first child process running
	   in a new session without a controlling termination
	*******************************************************/
	setsid();

	/*************************************************
	4. generate the second child process, to ensure
	   that the daemon cannot open a terminal file
	   to become its controlling termination
	**************************************************/
	a = fork();
	if(a > 0)
		exit(0);

	/*********************************************************
	5. detach the daemon from its original process group, to
	   prevent any signal sent to it from being delivered
	**********************************************************/
	setpgrp();

	/*************************************************
	6. close any file descriptor to release resource
	**************************************************/
	max_fd = sysconf(_SC_OPEN_MAX);
	for(i=0; i<max_fd; i++)
		close(i);

	/******************************************
	7. clear the file permission mask to zero
	*******************************************/
	umask(0);

	/****************************************
	8. change the process's work directory,
	   to ensure it won't be uninstalled
	*****************************************/
	chdir("/");


	// Congratulations! Now, this process is a DAEMON!
	pause();
	return 0;
}