【Linux】守护进程

1 相关概念

1.1 守护进程的概念

守护进程也叫做精灵进,是运行在后台的一种特殊进程。它独立于控制终端并且可以周期性的执行某种任务或者处理某些发生的事件。

  • 守护进程是非常有用的进程,在Linux当中大多数服务器用的就是守护进程。比如,web服务器http等,同时守护进程完成很多系统的任务。当Linux系统启动的时候,会启动很多系统服务,这些进程服务是没有终端的,也就是你把终端关闭了,这些系统服务是不会停止的,它们一直运行着。它们有一个名字,就叫做守护进程。

一般以服务器的方式工作,对外提供服务的服务器,都是以守护进程(精灵进程的方式在服务器中工作的,一旦启动之后,除非用户主动关闭,否则,一直会在运行。)

1.2 进程组和会话

进程组的相关概念:

  • 进程除了有进程的PID之外,还有一个进程组,进程组是一个进程或者多个进程组成。通常他们与同一作业相关联,可以收到同一终端的信号;
  • 每个进程组有唯一的进程组ID,每一个进程组有一个进程组组长。如何判断一个进程是不是这个进程组的组长?通常进程ID等于进程该进程组ID,那么该进程就是该进程组的组长。

会话组的相关概念:

  • 会话是有一个或者多个进程组组成的集合
  • 一个会话可以有一个终端,建立与控制终端连接的会话首进程被成为控制进程,一个会话的几个进程组可以分为前台进程和后台进程,而这些进程组的控制终端相同,也就是sesion id是一样的。当用户使用Ctrl + c 产生SIGINT信号时,内核会发送信号给相应的前台进程组的所有进程。
  • 如果运行一个程序,我想把它放到后台运行,可以在可执行程序后面加一个&;
  • 如果想把后台进程提到前台,可以使用fg
  • jobs指令可以查看当前会话的后台进程
  • 将前台进程放到后台,Ctrl + z  |  bg + 任务编号

观察现象:

 下面来介绍上述选项的意义:

 

 

 

 

 

 

综上:

  • 我们在命令行中启动一个进程,现在就可以叫做在会话中启动一个进程组,来完成某种任务;
  • 所有会话内的进程fork创建子进程,一般而言依旧属于当前会话。

像平时,当我们觉得Windows卡顿的时候,我们可能会重新注销一下。注销就是让用户退出登录后再重新登陆,那么此时就相当于给你新建一个会话。卡顿是因为你本次登陆过程中启动了很多任务,且都属于同一个会话,注销本质就是把你内部会话的所有进程组删掉。

注意:

  • 在登录的状态时,新起了一个网络服务器,创建好之后,在派生的子进程也属于当前会话,所以我们就不能让这个网络服务器属于这个会话内容,要不然它会受到用户的登录和注销的影响。
  • 所以,当我们有个网络服务的时候,应该脱离这个会话,让它独立的在计算机里自成进程组,自成新会话。这样在两个用户同时登录的时候,形成的两个会话是独立的,在操作各自的bash不会相互影响。
  • 像这种自成进程组,自成新会话,而且周而复始的进程称为守护进程(精灵进程)。

2 守护进程的方式

我们这里有三种方式让自己的进程守护进程化:

  • 自己写daemon函数,推荐使用这种方式
  • 用系统的daemon函数
  • nohup命令

2.1 TCP网络程序(守护进程化)

之前的TCP网络程序是在前台运行的,但是实际上服务器并不是在前台运行的,而是在后台运行的。所以现在对TCP网络程序的代买进行修改,加上一个小组件,使其守护进程化,让服务器在后台运行。编写daemon.hpp文件完成守护进程的主要逻辑,具体如下:

  1. 忽略一些不需要的异常信号,防止进程被信号杀死,如:调用signal函数忽略SIGPIPE信号;
  2. 更改进程的工作目录(选做);
  3. fork创建子进程,exit让父进程退出。让执行服务的进程不是进程组组长,从而保证后续不会再和其他终端相关联;
  4. 调用setsid函数设置自己是一个独立的会话(setsid不能设置进程组组长的进程);
  5. 将标准输入、标准输出、标准错误重定向到/dev/null(一种文件,不能写也不能读);

进程守护化需要调用setsid()函数,注意点如下:

  • 调用setsid创建新会话的目的,是让当前进程自成会话,与当前bash脱离关系(创建守护进程的核心)。
  • 调用setsid创建新会话时,要求调用进程不能是进程组长,但是当我们在命令行上启动多个进程协同完成某种任务时,其中第一个被创建出来的进程就是组长进程,因此我们需要fork创建子进程,让子进程调用setsid创建新会话并执行后续代吗,而父进程直接exit退出即可。此时子进程就不是组长进程了,而是独立会话的守护进程。
  • 当服务端给客户端写入时,但是客户端突然关掉了,那就是向一个不存在的文件描述符写入,此时服务端会收到SIGPIPE信号而自动终止,所以我们要忽略该信号。
  • 当前进程有自己的工作目录,有时候守护进程想要更改自己的工作目录,一般会将守护进程的工作目录设置为根目录,便于让守护进程以绝对路径的形式访问某种资源。我们可以使用chdir函数更改进程的工作目录,不过此操作不做强求。
  • 守护进程不能直接和用户交互,也就是说守护进程与终端去关联了,因此一般我们会将守护进程的标准输入。标准输出、标准错误都重定向到/dev/null,/dev/null是一个字符文件(设备),类似于Linux的一个“文件黑洞”or“垃圾桶”,通常用于屏蔽/丢弃输入输出信息。(建议这么做)

daemon.hpp实现如下

#pragma once#include <cstdlib>
#include <cstring>
#include <signal.h>
#include <unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include "log.hpp"
#include "err.hpp"//守护进程的本质:孤儿进程
void Daemon()
{// 1. 忽略异常信号signal(SIGCHLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);// 2. 创建子进程,让子进程成为新的会话if (fork() > 0)exit(0); // 父进程退出// 子进程// 3. 设置子进程为新会话pid_t id = setsid();if (id < 0){logMessage(Fatal, "setsid error:%s\n", strerror(errno));exit(SETSID_ERR);}logMessage(Info, "setsid successful.\n");//4. 可选,更改工作目录//chdir("/");//5. 处理0,1,2的问题int fd=open("/dev/null",O_RDWR);if(fd<0){logMessage(Fatal,"open /dev/null error:%s\n",strerror(errno));exit(OPEN_ERR);}logMessage(Info,"open /dev/null successful!\n");dup2(fd,0);dup2(fd,1);dup2(fd,2);close(fd);
}

出现问题:进程变成守护进程后,打印的日志信息不见了,要怎么办?

解决问题:日志持久化,将日志输出追加打印到log.txt文件中!


最后一个步骤:我们只需要在服务端的main函数命令行参数信息处理后调用此daemon函数即可:

 

 测试结果:

  • 现在我们运行服务端,通过下面的监控脚本辅助观察信息:
[xzy@ecs-333953 tcp]$ ps axj | head -1 && ps axj | grep serverTcp
[xzy@ecs-333953 tcp]$ ps axj | head -1 && ps axj | grep sshd

 

 2.2 TCP网络编程代码

lesson25/tcp · 杰编程/LinuxCode - 码云 - 开源中国 (gitee.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/82379.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用MethodInterceptor和ResponseBodyAdvice做分页处理

目录 一、需求 二、代码实现 父pom文件 pom文件 配置文件 手动注册SqlSessionFactory&#xff08;MyBatisConfig &#xff09; 对象 实体类Users 抽象类AbstractQuery 查询参数类UsersQuery 三层架构 UsersController UsersServiceImpl UsersMapper UsersMapper.…

HOperatorSet.OpenFramegrabber “GigEVision“

HOperatorSet.OpenFramegrabber "GigEVision"访问失败 直接跳出 但其他算子可以访问 重装halcon x86

小程序裂变怎么做?小程序裂变机制有哪些?

做了小程序就等于“生意上门”&#xff1f;其实并不是这样。小程序跟流量平台较为明显的区别就在于小程序并非“自带流量”&#xff0c;而是需要企业利用自己的营销推广能力来建立引流渠道&#xff0c;从而完成用户的拉新和留存、转化。因此&#xff0c;想要用小程序来增加自己…

RaabitMQ(三) - RabbitMQ队列类型、死信消息与死信队列、懒队列、集群模式、MQ常见消息问题

RabbitMQ队列类型 Classic经典队列 这是RabbitMQ最为经典的队列类型。在单机环境中&#xff0c;拥有比较高的消息可靠性。 经典队列可以选择是否持久化(Durability)以及是否自动删除(Auto delete)两个属性。 Durability有两个选项&#xff0c;Durable和Transient。 Durable表…

3分钟创建新生分班查询二维码,无需技术、0成本

作为教师&#xff0c;我们深知分班是一项极其重要的任务&#xff0c;需要综合考虑学生的性格、能力和兴趣等多个方面&#xff0c;以确保每个学生都能够获得最佳的学习环境和成绩。在本文中&#xff0c;我将分享一种便捷的方式来告知家长有关分班录取情况的方法。 通常&#xf…

python中 “”和“and”的区别

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 1、“&”和“and”有本质区别&#xff0c;属于不同类型的运行符号。& 是位运算&#xff1b;and 是逻辑运算。 2、首先是&&#xff1a;该运输符属于字符串的连接运算符&#xff0c;例如&#xff0c;“w“&”c…

【LeetCode】数据结构题解(9)[复制带随机指针的链表]

复制带随机指针的链表 &#x1f609; 1.题目来源&#x1f440;2.题目描述&#x1f914;3.解题思路&#x1f973;4.代码展示 所属专栏&#xff1a;玩转数据结构题型❤️ &#x1f680; >博主首页&#xff1a;初阳785❤️ &#x1f680; >代码托管&#xff1a;chuyang785❤…

el-select与el-tree结合使用,实现select框下拉使用树形结构选择数据

使用el-select与el-tree&#xff0c;实现如下效果&#xff0c; 代码如下&#xff1a; 注意点&#xff1a;搜索input框的代码一点放在option上面&#xff0c;不要放在option里面&#xff0c;否则一点击搜索框&#xff0c;下拉框就会收起来&#xff0c;不能使用。 <el-select…

wxwidgets Ribbon使用wxRibbonToolBar实例

wxRibbonToolBar就是工具栏&#xff0c;一下是实现的效果&#xff0c;界面只是功能展示&#xff0c;没有美化 实现代码如下所示&#xff1a; MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600)) …

锐捷VSU技术理论与实验

目录 VSU涉及的相关基础概念 VSU的2种工作模式 VSU的3种设备角色 VSU的4种设备状态 VSU的分裂与合并 VSU建立过程 双主检测 VSU报文转发原理 VSU命令配置 配置VSU 配置双主检测 VSU涉及的相关基础概念 域编号&#xff08;Domain ID&#xff09; Domain ID是VSU的标…

【C++】bind包装器

bind包装器 调用bind的一般形式&#xff1a;auto newCallable bind(callable,arg_list); 其中&#xff0c;newCallable本身是一个可调用对象&#xff0c;arg_list是一个逗号分隔的参数列表&#xff0c;对应给定的 callable的参数。 当我们调用newCallable时&#xff0c;newCa…

【硬件设计】模拟电子基础三--集成运算放大电路

模拟电子基础三--集成运算放大电路 一、集成运算放大器1.1 定义、组成与性能1.2 电流源电路1.3 差动放大电路1.4 理想运算放大器 二、集成运算放大器的应用2.1 反向比例运算电路2.2 同向比例运算电路2.3 反向加法运算电路2.4 反向减法运算电路2.5 积分运算电路2.6 微分运算电路…

数据结构【图的类型定义和存储结构】

数据结构之图 图的定义和概念图的定义图的术语 图的类型定义图的存储结构数组&#xff08;邻接矩阵&#xff09;表示法无向图的邻接矩阵表示法有向图的邻接矩阵表示法网&#xff08;即有权图&#xff09;的邻接矩阵表示法 邻接矩阵的ADT定义邻接表&#xff08;链式&#xff09;…

opencv-32 图像平滑处理-高斯滤波cv2.GaussianBlur()

在进行均值滤波和方框滤波时&#xff0c;其邻域内每个像素的权重是相等的。在高斯滤波中&#xff0c;会将中心点的权重值加大&#xff0c;远离中心点的权重值减小&#xff0c;在此基础上计算邻域内各个像素值不同权重 的和。 基本原理 在高斯滤波中&#xff0c;卷积核中的值不…

【图像去噪】基于进化算法——自组织迁移算法(SOMA)的图像去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

vue3实现自定义select下拉框内容之城市区域篇

分享-2023年资深前端进阶&#xff1a;前端登顶之巅-最全面的前端知识点梳理总结 *分享一个使用比较久的&#x1fa9c; 需求分析&#xff1a; 1、实现一个区域下拉选项与现有ui组件库不同&#xff0c;支持多选、单选需求 2、支持选中区域后-全选中当前区域下的所有城市信息 3、…

项目实战 — 消息队列(5){统一硬盘操作}

前面已经使用数据库管理了交换机、绑定、队列&#xff0c;然后又使用了数据文件管理了消息。 那么&#xff0c;这里就创建一个类&#xff0c;讲之前的两个部分整合起来&#xff0c;对上层提供统一的一套接口&#xff0c;表示硬盘上存储的所有的类的信息。 /* * 用这个类来管理…

企业计算机服务器中了locked勒索病毒怎么办,如何预防勒索病毒攻击

计算机服务器是企业的关键信息基础设备&#xff0c;随着计算机技术的不断发展&#xff0c;企业的计算机服务器也成为了众多勒索者的攻击目标&#xff0c;勒索病毒成为当下计算机服务器的主要攻击目标。近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的服务器被locked…

Unico-GUI软件关于ST传感器机器学习(MLC)基本操作步骤

准备工作 UNICO-GUI软件用于意法半导体产品组合&#xff08;加速度计、陀螺仪、磁力计和环境传感器&#xff09;中所有MEMS传感器的评估板。它可用于Linux&#xff08;基于Debian&#xff09; / Mac OS X / Windows平台。 Unico-GUI - MEMS evaluation kit software package …

优维低代码实践:对接数据

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…