1.守护进程概念

1.什么是守护进程

  • Linux Deamon守护进程是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或者等待处理某些事件的发生

  • 它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的

  • 它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的

  • 守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。

  • 一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。
    在这里插入图片描述

  • 一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。

2.守护进程的特点

  • 守护进程都具有超级用户的权限。

  • 守护进程的父进程是init进程。

  • 守护进程都不用控制终端,其TTY列以“?”表示,TPGID为-1.

  • 守护进程都是各自进程组合会话过程的唯一进程。

3.如何查看linux系统中已存在的守护进程

ps axj		#查看系统中的守护进程
ps axj |grep daemon		#使用管道过滤想要查看的守护进程

在这里插入图片描述
在这里插入图片描述

2.守护进程编写的步骤

  • 创建子进程,父进程退出
m_pid = fork();//创建子进程
if (m_pid < 0)
{
	exit(1);
}
else if (m_pid > 0)
{
	exit(0);//父进程退出
}
  • 在子进程中创建新对话
setsid();//若当前进程不是进程组长,创建一个新会话;若当前进程已经是进程组长,返回错误
  • 改变当前目录为根目录
chdir("/");
  • 重设文件权限掩码
umask(0);//设置进程的权限掩码,参数0表示:可以设置任何权限(读、写、执行)
  • 关闭文件描述符
for (int i = 0; i < getdtablesize(); i++) {
	close(i);
	printf("文件描述符关闭成功!");
}
  • 守护进程退出处理

3.示例

完整示例:

/*
* 守护进程
*/

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <ctime>
#include <stdio.h>
#include <cstdlib>
#include <sys/stat.h>
#include <time.h>
#include <assert.h>
#include <unistd.h>

int main()
{
	// 1.在父进程中执行fork并exit退出;
	pid_t m_pid;
	m_pid = fork();//创建子进程

	if (m_pid < 0)
	{
		exit(1);
	}
	else if (m_pid > 0)
	{
		exit(0);//父进程退出
	}

	// 2.在子进程中调用setsid函数创建新的会话;
	setsid();//若当前进程不是进程组长,创建一个新会话;若当前进程已经是进程组长,返回错误

	// 3.调用getcwd()函数获取当前目录路径,并在子进程中调用chdir函数,让根目录 ”/” 成为子进程的工作目录;
	char m_path[1024];
	if (getcwd(m_path, sizeof(m_path)) == NULL)
	{
		perror("get path error!");
		exit(1);
	}
	printf("get path success !");

	chdir("/");

	// 4.在子进程中调用umask函数,设置进程的umask为0
	umask(0);//设置进程的权限掩码,参数0表示:可以设置任何权限(读、写、执行)

	// 5.在子进程中关闭任何不需要的文件描述符
	for (int i = 0; i < getdtablesize(); i++) {
		close(i);
		printf("文件描述符关闭成功!");
	}


	printf("守护进程构建成功!");
	while (1) {
		/*
		* do anything...
		*/

		FILE* fp = fopen("/tmp/mytest.log", "a");
		assert(fp != NULL);

		time_t rawtime;
		struct tm* ptminfo;

		time(&rawtime);
		ptminfo = localtime(&rawtime);
		printf("current: %02d-%02d-%02d %02d:%02d:%02d\n",
			ptminfo->tm_year + 1900, ptminfo->tm_mon + 1, ptminfo->tm_mday,
			ptminfo->tm_hour, ptminfo->tm_min, ptminfo->tm_sec);

		fprintf(fp, "守护进程测试:%02d-%02d-%02d %02d:%02d:%02d\n\n", ptminfo->tm_year + 1900, ptminfo->tm_mon + 1, ptminfo->tm_mday,
			ptminfo->tm_hour, ptminfo->tm_min, ptminfo->tm_sec);
		fclose(fp);
		sleep(5);
	}

}

编译执行结果
在这里插入图片描述
运行后日志打印:

在这里插入图片描述

Logo

更多推荐