进程守护化

news2024/11/27 21:42:33

文章目录

  • 概念引入
  • ps细节展示
    • 什么是进程组
    • 什么是会话
    • 细节演示
    • 有关指令的处理
  • 用户级任务和进程组的关系
    • 关系
    • 不同
  • 什么是守护进程
    • 如何创建守护进程
  • 代码说明
    • 如何关闭守护进程
  • 问题

概念引入

我们在之前的章节中已将看过进程相关的概念, 本篇介绍守护进程
进程还有进程组, 作业, 会话的概念
终端进程的启动父进程都是bash

ps细节展示

当我们在终端输入sleep10000, 查看这个进程相关的信息
在这里插入图片描述

其中的信息是
SID表示是会话
STAT表示状态
TTY表示是当前打开的终端是谁
UID表示用户身份, 当前sleep进程是以用户UID为1000的用户执行的进程
可以看到这个sleep进程的PIDPGID一样, 这样的进程自成进程组
进程的PIDPGID一样, 这样的进程自成进程组
进程组默认是在一个会话中的

什么是进程组

当输入指令 sleep 1000 | sleep 2000 | sleep 3000
同时启动的多个进程, 是属于同一个进程组的
在这里插入图片描述每次登陆Linux, 系统都会给用户提供,

  1. bash
  2. 提供一个终端, 用于给用户提供命令行解析服务

什么是会话

其中, 这个1和2在一起, 这个叫一个会话
在命令行中启动的所有的进程, 最终默认都是在当期会话内部的一个进程组(可以是一个进程自成为进程组)

当我们建立三个终端时, 此时查看bash进程
对于每一个bash都是自成进程组, 自成会话

在这里插入图片描述清理所有的任务, 首先执行sleep 100000
再执行, sleep 20000 |sleep 300000 | sleep 40000
再次查看进程信息

在这里插入图片描述
其中sleep 100000 是自成进程组, 自成会话
另外三个是为一组进程组, 但因为是同属一个终端的指令, 所以是属于一个会话
画图演示具体细节:

细节演示

在这里插入图片描述

有关指令的处理

1.jobs查看当前会话中的所有进程
2. ctrl + z将当前进程放在后台

  1. 放在后台的应用, 默认从1开始有作业编号
  2. 放在后台的进程, 默认会处于stopped, 可以使用bg %作业编号的方式, 恢复进程为running, 也可以使用bg, 不加编号, 默认是最近的一次被挂起(ctrl + z)的作业
  3. 使用指令fg %+作业编号的数字, 可以将任务放在前台, 也可以简单使用fg, 不加编号也行, 与上述同理

用户级任务和进程组的关系

关系

  1. 进程组: 技术方面的表述
  2. 用户级任务: 用户级概念

不同

每次启动Linux都会创建一个新的会话, 会话与会话之间是隔离的
在这里插入图片描述

每次启动的进程是受到用户登录和注销影响的, 如果这个进程出现异常, 那么有可能会导致这个bash会话被关闭, 这与OS的处理机制有关
现在想让我们的服务(进程), 不受用户的登录和注册影响, 那么只需要 把这个进程变成守护进程

什么是守护进程

  1. 守护进程是一个独立的会话
  2. 不隶属于任何一个bash会话

如何创建守护进程

使用setsid接口
在这里插入图片描述
进程在调用这个会话的时候, 该进程会自己成为一个会话, 未来这个会话中只有我自己
前提是, 这个进程不是进程组的组长, 组长一般是多个进程的第一个
所以要成功调用, 一般是创建子进程, 让父进程直接退出
即守护进程一定是孤儿进程, 他的父进程一定是bash进程(1)

代码说明

Deamon.hpp

#pragma once
#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const char *root = "/";
const char *dev_null = "/dev/null";

void Deamon(bool ischdir, int isclosefd)
{
    // 1.忽略可能引起进程异常的信号(取决于应用场景)
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    // 2.让自己不要成为组长
    if (fork() > 0)
        exit(0); // 父进程退出

    // 3.设置让自己成为一个新的会话, 后面的代码是子进程在走
    setsid();

    // 4.每一个进程都有自己的CWD(PWD的路径), 是否将当前进程的CWD设置成根目录(好处是, 这样的顶级方式查找)
    // 1. 防止依赖临时文件
    // 守护进程通常不需要访问任何特定的文件或目录。如果守护进程在其启动时的工作目录中创建了临时文件或其他资源,可能会导致不必要的依赖。将 CWD 设置为根目录可以确保守护进程不会依赖于任何特定的工作目录。
    // 2. 避免权限问题
    // 如果守护进程在其启动时的工作目录中创建文件或修改文件,可能会遇到权限问题。例如,如果守护进程运行在非特权用户账户下,而该用户的家目录或工作目录可能不具备相应的写权限,这会导致守护进程无法正常工作。将 CWD 设置为根目录可以避免这些问题。
    // 3. 减少对系统的影响
    // 将 CWD 设置为根目录可以减少守护进程对其启动环境的依赖,从而减少其对系统的影响。这意味着守护进程不会意外地修改或依赖于其启动时的工作目录中的文件或目录。
    // 4. 便于管理和维护
    // 将 CWD 设置为根目录可以使守护进程的管理和维护更加简单。例如,如果守护进程需要在日志中记录其工作目录,将 CWD 设置为根目录可以确保日志的一致性和可预测性。
    // 5. 避免挂载点问题
    // 如果守护进程在其启动时的工作目录位于一个挂载点上(例如,一个可移动设备或网络文件系统),那么如果该挂载点变得不可用(例如,设备断开连接或网络中断),守护进程可能会出现问题。将 CWD 设置为根目录可以避免这些问题。
    if (ischdir)
        chdir(root); // 更改目录为根目录

    // 5.守护进程是一个独立的会话, 不需要和用户的输入输出进行关联, 关闭标准输入输出(不推荐, 万一真的存在从哪个文件读取输入到另一个文件, 此时就会出错)
    // 所以好的做法是使用 /dev/null, 向这个文件写入的任何东西都会丢弃, 读的时候读到文件结尾
    int fd = open(dev_null, O_RDWR);
    if (isclosefd) // 是否是直接关闭文件描述符的方式
    {
        close(0);
        close(1);
        close(2);
    }
    else // 重定向到null文件的形式
    {
        if (fd > 0)
        {
            // int dup2(int oldfd, int newfd);
            dup2(fd, 0);
            dup2(fd, 1);
            dup2(fd, 2);
            close(fd);
        }
    }
}

main.cc

#include "Daemon.hpp"
#include <unistd.h>
int main()
{
    // 守护进程
    Deamon(false, false);
    // 要执行的核心代码
    while(1)
    {
        sleep(1);
    }


    return 0;
}

结果演示
在这里插入图片描述
在这里插入图片描述
父进程为bash, 为一个会话组
其中, 这个tty为?, 表示终端无关性

当关闭这个终端, 再次启动查看, 他还是存在, 且信息表示的内容与当期一样
查看信息 ls /proc/3596 -l, 里面都是该守护进程系相关的信息
在这里插入图片描述
在查看这个fd文件夹查看文件描述符信息
在这里插入图片描述

如何关闭守护进程

那要停止这个守护进程就需要使用kill -9 ID, 更推荐使用信号处理机制, 在代码当中, 发送某个信号时, 首先会进行资源的安全关闭, 再进行退出操作, 这边就不再修改
当然相比上述的守护进程的启动, 更推荐使用这样的方式来启动
在这里插入图片描述
在这里插入图片描述

问题

  1. 系统有没有提供进程变为守护进程的方式呢?
    在这里插入图片描述
  2. 之前的tcpserver udpserver怎么转化为守护进程呢?
    以tcpserver为例:
    server是在Main.cc文件内的, 所以对此进行修改, 还要将名字改为tcp_serverd, 这样专业一点, 因为守护进程都是以d结尾的, 就像mysql 的服务叫做mysqld
    同时, tcpserver的日志显示是要保存在文件中更好一点的

综上, 这个代码可以为:
在这里插入图片描述
其他的不变, 这样一个服务器的雏形就有了
日志正常

在这里插入图片描述serverd启动正常, 服务正常
在这里插入图片描述
守护进程完成

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue脚手架项目创建 --保姆级教程

Vue-项目创建 这里我默认已经安装好了脚手架&#xff0c;没装得可以看我上篇博客的安装教程。脚手架安装教程 脚手架提供了两种创建方式&#xff0c;我们以 vue ui 作为示例…… 1.输入 vue ui 进入图形界面进行项目配置 选择 一个你 的项目的存放路径&#xff0c;各自都不相…

[算法] 数组

1 二分查找 . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/binary-search/submissions/570732311/ 前闭后闭 class …

Word 中脚注和尾注的区别有哪些?如何正确使用它们?

在撰写学术论文、报告或其他需要引用资料的文章时&#xff0c;脚注和尾注是两种常用的标注方法。它们不仅可以为读者提供额外的背景信息&#xff0c;还能帮助整理文章中的引用来源。下面我们就来详细的了解一下什么是脚注和尾注。 脚注 脚注&#xff08;Footnote&#xff09;…

大学离散数学:开启逻辑与思维的奇妙之旅

在大学的知识殿堂中&#xff0c;离散数学犹如一颗璀璨的明珠&#xff0c;散发着独特的魅力。 离散数学是现代数学的一个重要分支&#xff0c;它主要研究离散对象的结构及其相互关系。与连续数学不同&#xff0c;离散数学处理的是离散的、可数的对象&#xff0c;如整数、图、集…

Kubernetes简介与部署+Pod管理与优化

一、简介 1.基础信息 在Docker 作为高级容器引擎快速发展的同时&#xff0c;在Google内部&#xff0c;容器技术已经应用了很多年Borg系统运行管理着成干上万的容器应用。Kubernetes项目来源于Borg&#xff0c;可以说是集结了Borg设计思想的精华&#xff0c;并且吸收了Borg系统…

动态线程池设计与实现

为什么要有动态线程池 ThreadPoolExecutor 核心线程参数对某些业务不知到设置多少合适调整参数需要重新启动服务没有告警功能 设计思路 流程设计 库表抽象 更新操作流程图 代码实现 GitCode - 全球开发者的开源社区,开源代码托管平台

C++ 内部类

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 概念概述 如果一个类定义在另一个类的内部&#xff0c;这个内部类就叫做内部类。内部类…

(02)python-opencv图像处理——更改颜色空间HSV

前言 1、更改颜色空间 1.1BGR 到 Gray 的示例 1.2 BGR 到 HSV 的示例&#xff1a; ​编辑 1.3 通过HSV进行颜色追踪 1.3.1hsv cv.cvtColor(frame, cv.COLOR_BGR2HSV) 1.3.2 BGR vs HSV&#xff1a; 1.3.3 为什么使用 HSV 颜色空间&#xff1f; 1.3.4 cv.inRange(hsv…

oracle-函数-instr()的妙用以及相似功能like

INSTR(C1,C2[,I[,J]]) 【功能】在一个字符串中搜索指定的字符,返回发现指定的字符的位置; 【说明】多字节符(汉字、全角符等)&#xff0c;按1个字符计算 【参数】 C1 被搜索的字符串 C2 希望搜索的字符串 I 搜索的开始位置,默认为1 J 第J次出现的位置,默认为1 【…

安全帽未佩戴预警系统 劳保防护用品穿戴监测系统 YOLO

在建筑、矿山、电力等高危行业中&#xff0c;工人面临着各种潜在的危险&#xff0c;如高空坠物、物体打击等。安全帽能够有效地分散和吸收冲击力&#xff0c;大大降低头部受伤的严重程度。一旦工人未正确佩戴安全帽&#xff0c;在遭遇危险时&#xff0c;头部将直接暴露在危险之…

Linux网络编程 -- 网络套接字预备与udp

本文主要介绍网络编程的相关知识&#xff0c;在正式介绍网络编程之前&#xff0c;我们得先了解一些前置的知识。 1、端口号 我们上网其实就是两种动作&#xff0c;一个是将远处的数据拉取到本地&#xff0c;另一个是把我们的数据发送给远端。其实大部分的网络通信行为都是用户…

基于springboot vue3 工商局商家管理系统设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm springcloud等开发框架&#xff09; vue .net php phython node.js uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作☆☆☆ 精彩专栏推荐订阅☆☆☆☆…

【公共祖先】二叉树专题

里面涉及多个plus题 前言1.二叉树的最近公共祖先2.二叉搜索树的最近公共祖先3.二叉树的最近公共祖先II4.二叉树的最近公共祖先III5.二叉树的最近公共祖先IV 前言 公共祖先这一类题目&#xff0c;难度不大&#xff0c;但是非常实用&#xff0c;也是面试问到概率比较大的一类题目…

夜间数据库IO负载飙升?MySQL批量删除操作引发的问题排查

目录 问题现象 问题分析 修改建议 总结 问题现象 近日&#xff0c;某用户反馈他们的MySQL数据库实例在凌晨时段会频繁出现IO负载急剧上升的情况&#xff0c;这种状态会持续一段时间&#xff0c;随后自行恢复正常。为了查明原因&#xff0c;该用户通过DBdoctor工具收集了相…

DLL中函数导出时的注意事项

1.使用.def文件导出函数 1.1示例代码:使用stdcall 关键字 和 extern "C" 关键字修饰 dll中函数 BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) {switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:case DLL_THREAD_ATT…

sahi密集检测的推理技巧

最近在做一些计数的项目&#xff0c;样本中存在一些非常密集的目标&#xff0c;如果混杂一起训练指标很难达到要求&#xff0c;所以考虑在训练时不加入密集目标&#xff0c;训练使用正常的样本&#xff0c;在推理时使用密集检测方案。 在高分辨率图像中检测小目标一直是一个技…

【Qt+Python项目构建】- 02 Qt creator 14.0 + PySide6 如何让图像控件的尺寸变化和窗口一致

前言&#xff1a;【这是个AI不会回答的问题】 Qt Creator 新的版本又发出了&#xff0c;Pyside6 有很多新功能。但是&#xff0c;一些传统的方法要被淘汰了。 一个经典的例子是&#xff1a; 我有个一个图像要显示在Form里面的图像控件上&#xff0c;OK&#xff0c; 我现在拖…

Unity实现自定义图集(一)

以下内容是根据Unity 2020.1.0f1版本进行编写的   Unity自带有图集工具,包括旧版的图集(设置PackingTag),以及新版的图集(生成SpriteAtlas)。一般来说,unity自带的图集系统已经够用了,但是实际使用上还是存在一些可优化的地方,例如加载到Canvas上的资源,打图集不能…

JVM(学习预热 - 走进Java)(持续更新迭代)

目录 一、彻底认识Java虚拟机 开创世纪&#xff1a;Sun Classic 开创世纪&#xff1a;Exact VM 武林霸主&#xff1a;HotSpot VM 移动端虚拟机&#xff1a;Mobile/Embedded VM “三大”其二&#xff1a;BEA JRockit/IBM J9 VM 软硬结合&#xff1a;BEA Liquid VM/Azul VM…

更新子节点的优化策略1:目标old节点的位置预测

更新子节点的优化策略1&#xff1a;目标old节点的位置预测&#xff1a; 如果 oldStartVnode 和 newStartVnode 是同一个节点&#xff0c;直接 patchVnode&#xff0c;同时 oldStartIdx、newStartIdx 索引都加 1&#xff08;向右移动&#xff09;如果 oldEndVnode 和 newEndVno…