Linux网络:守护进程

Linux网络:守护进程

    • 会话
      • 进程组
      • 会话
      • 终端
    • 守护进程
      • setsid
      • daemon


在创建一个网络服务后,往往这个服务进程是一直运行的。但是对于大部分进程来说,如果退出终端,这个终端上创建的所有进程都会退出,这就导致进程的生命周期与终端绑定,如果终端退出,服务就无法继续运行了。

为此,创建一个服务进程后,需要让其不在受到终端的影响,就算终端退出,进程依然执行,这种进程称为守护进程

在讲解如何创建一个守护进程之前,先了解一些Linux中与会话相关的知识。

会话

进程组

进程组是一个或者多个进程的集合,这些进程都有同样的进程组ID(PGID),这个ID和PID类似,都是一个正整数,可以放在pid_t类型中。

往往一个进程组内部的所有进程,要共同完成一个功能,这些进程之间可以进行通信。而当在Linux中通过管道命令创建多个进程,此时Linux认为多个进程是共同完成一个功能的,就会把它们放到同一个进程组中。

通过管道创建三个sleep进程:

在这里插入图片描述

创建进程后,通过ps -ajx查看进行信息,可以看到三个经常的PGID都是54844,也就是sleep 100这条命令的PID。这说明这三个由管道串联起来的进程,属于同一个进程组。而sleep 100这个进程是进程组长

进程组长往往是进程组中的第一个进程,其可以在当前进程组中创建新的进程,也可以创建一个新的进程组。

但是如果进程组长退出了,不代表进程组退出了,就算进程组长退出了,只要进程组中还有进程,那么这个进程组依然存在。

在这里插入图片描述

通过kill杀掉组长进程后,剩余的两个进程依然存在,并且PGID依然是54844


会话

一个Linux系统,可以有多个会话,每个会话都是一个或多个进程组的集合。

创建一个新的会话,并在会话中执行三个sleep进程:

在这里插入图片描述

在原先的会话中,查看bash进程和sleep进程的信息:

在这里插入图片描述

此处-E "bash|sleep"表示查找bash或者sleep进程。

其中SID表示会话ID,可以看到第一个bashSID = 53792,第二个bashSID = 54989

这两个bash本身也是进程,它们的PID == PGID == SID。这种PID == SID的进程,称为话首进程,它是会话中的第一个进程。一般而言,话首进程都是bash

而创建的三个sleep进程,它们的SID = 54989,与第二个bash相同,说明它们属于同一个会话,而54989会话中,包含四个进程以及两个进程组。而53792会话中只有一个进程和一个进程组。

这说明一个会话是一个或多个进程组的集合。当一个话首进程退出,这个会话内部的所有进程都会退出

在一个会话中创建三个sleep进程:

在这里插入图片描述

随后把bash话首进程杀掉:

在这里插入图片描述

可以看到,不仅仅话首进程退出了,三个sleep进程一起退出了。


终端

一个会话不仅仅包含多个进程组,它还需要一个控制终端,来接受用户的指令。

当创建一个会话,会执行以下两步:

  1. 创建一个终端
  2. 启动一个bash进程(组)

终端本质上是一个Linux的文件,存在于/dev/pts目录下。

在这里插入图片描述

当前我创建了两个会话,那么就有两个终端,这两个终端分别对应01这两个文件。

如果尝试删除这些文件会被拒绝,哪怕你是root用户,因为这些文件是由内核管理的。

除去两个终端文件,还有一个ptmx,这个文件是用于创建终端的文件,如果这个文件丢失,可能就无法创建新的终端了。

在一个会话中,包含多个进程组,这些进程组分为两类:

  1. 前台进程组:一个会话只有一个,这个进程组独占终端的输入输出流
  2. 后台进程组:一个会话可以有多个,无法接收到来自终端的数据,在后台运行

在这里插入图片描述

比如向终端输入ctrl + c,就是一个中断信号,此时这个信号会发送给前台进程,导致前台进程退出。

但是并不是所有的信号都直接发送给前台进程组,因为有一个特殊的bash进程,如果某些信号的功能是直接挂断整个会话,那么这个信号会发送给bash,哪怕bash不是当前的前台进程组。

至此,可以这样理解Linux中的会话机制:

  1. 一个进程组管理多个进程,这些进程往往共同完成一个功能
  2. 一个会话管理多个进程组,当会话退出,该会话下的所有进程组都退出
  3. 终端是会话的对外表现,一个会话只有一个进程组可以占用终端

刚才提到,一个终端本质就是/dev/pts下的一个文件,其实与终端交互,就是进程在读写这个文件。那么一个进程如何知道要读取/dev/pts下的哪一个文件?会话又是如何保证其下的所有进程都使用同一个终端的?

终端的信息存储在进程的PCB中,先前说过会话创建包括一个终端和一个bash,而这个过程中,会把这个终端的信息存储到bashPCB

而在一个会话中创建的所有进程,都是bash的后代进程,会继承来自bashPCB,也就会继承到PCB中的终端信息,从而保证同一会话的所有进程最后都操控同一个终端


守护进程

了解Linux的会话机制后,就可以谈一谈守护进程的问题了。

先前说过,当一个会话的话首进程退出,那么该会话的所有进程都会退出,因此一个守护进程一定不能属于其它会话,而是自己创建一个会话,自己就是话首进程

setsid

setsid可以创建一个新会话并把自己变成话首进程,需要头文件<sys/types.h><unistd.h>

函数声明:

pid_t setsid(void)

调用该函数有一个前提,该进程不能是进程组长

但是对于一个新创建的进程,它自成一个进程组,自己就是进程组长,如何才能让它不是进程组长?

尝试以下代码:

#include <unistd.h>int main()
{fork();while (true){}return 0;
}   

这个代码中,通过fork创建了一个子进程,随后父子进程同时陷入死循环。

运行代码:

在这里插入图片描述

此时终端被阻塞,切换到另一个终端,查看test.exe这个进程的信息。

在这里插入图片描述

此时查询到了两个进程,一个是父进程,另一个是子进程,重点在于它们的GPID都是52746,这说明通过fork创建的父子进程属于同一个进程组

frok创建的子进程会继承来自父进程的所有代码,PCB等信息。因此如果想要让一个进程调用setsid创建一个新会话,只需要通过fork创建一个子进程,子进程继承父进程的所有信息,但又不是进程组长,可以调用setsid

因此setsid的常见写法如下:

pid_t id = fork();
if (id > 0)exit(0);setsid();

这段代码中,通过fork创建一个子进程,此时父子进程属于同一个进程组,父进程是组长。如果id > 0说明是父进程,父进程直接退出,一个进程组中,进程组长退出,进程组其他进程继续运行,不会退出。因此子进程不会退出,继承了父进程的所有信息,并且还不是进程组长。

于是子进程调用setsid,自己创建一个会话,自己做话首进程,至此子进程就是一个守护进程了!

运行以下代码:

#include <unistd.h>
#include <sys/types.h>int main()
{pid_t id = fork();if (id > 0)exit(0);setsid();while (true){}return 0;
}

这个代码在子进程变为守护进程后,执行一个死循环。

在这里插入图片描述

执行./test.exe后,查看bashtest进程的信息,发现test.exe这个进程PID=PGID=SID=58278,并且不和任何一个bash重复。这说明test.exe已经自己创建一个会话,自己做话首进程,成为了一个守护进程了。

但是还有一个问题,那就是它的终端没有切断:

在这里插入图片描述

可以看到它的三个标准流,都指向/dev/pts/0,这就是当前的终端文件。如果当前终端退出,那么如果这个守护进程还向终端输出内容,就会导致错误,因此还要改变它的输出流:

// 关闭标准输入、输出和错误
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);// 打开/dev/null作为标准输入、输出和错误
open("/dev/null", O_RDONLY);
open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY);

此处的/dev/null是一个Linux提供的文件,它可以接收任何输入,但是不论输入什么都会被系统丢弃。因此如果一个程序有输出,但是又不希望接收到它的输出时,就可以把输出重定向到/dev/null下。


daemon

setsid的用法还是有点复杂了,为此Linux提供了另一个系统调用daemon,它封装了上述所有过程,可以快速创建一个守护进程。需要头文件<unistd.h>

函数声明:

int daemon(int nochdir, int noclose)

参数:

  • nochdir:改变工作目录
    • 传入0:改变工作目录为根目录
    • 传入1:保持当前工作目录
  • nclose:改变输入输出流
    • 传入0:输入输出流重定向到/dev/null
    • 传入1:不改变输入输出流

原先的代码就可以变成:

#include <unistd.h>
#include <sys/types.h>int main()
{daemon(0, 0);while(true){}return 0;
}

这就是一个功能全面的守护进程了。


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

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

相关文章

基于深度学习的文本信息提取方法研究(pytorch python textcnn框架)

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

Seatunnel解决Excel中无法将数字类型转换成字符串类型以及源码打包

需求 需要实现将Excel中的数字类型的单元格像数据库中字符串类型的字段中推送 问题原因 Seatunnel在读取字段类型的时候都是使用强转的形式去获取数据的 假如说数据类型不一样的话直接强转就会报错 修改位置 org/apache/seatunnel/api/table/type/SeaTunnelRow.java org…

AntFlow 0.11.0版发布,增加springboot starter模块,一款设计上借鉴钉钉工作流的免费企业级审批流平台

AntFlow 0.11.0版发布,增加springboot starter模块,一款设计上借鉴钉钉工作流的免费企业级审批流平台 传统老牌工作流引擎比如activiti,flowable或者camunda等虽然功能强大&#xff0c;也被企业广泛采用&#xff0c;然后也存着在诸如学习曲线陡峭&#xff0c;上手难度大&#x…

UniAPP快速入门教程(一)

一、下载HBuilder 首先需要下载HBuilder开发工具&#xff0c;下载地址:https://www.dcloud.io/hbuilderx.htmlhttps://www.dcloud.io/hbuilder.html 选择Windows正式版.zip文件下载。下载解压后直接运行解压目录里的HBuilderX.exe就可以启动HBuilder。 UniApp的插件市场网址…

计算机网络 (5)数据通信的基础知识

前言 数据通信是一种以信息处理技术和计算机技术为基础的通信方式&#xff0c;它通过数据通信系统将数据以某种信号方式从一处传送到另一处&#xff0c;为计算机网络的应用和发展提供了技术支持和可靠的通信环境&#xff0c;是现代通信技术的关键部分。 一、数据通信的基本概念…

K8s学习笔记之了解k8s的网络模型

文章目录 docker 网络模型容器与容器之间&#xff0c;容器与宿主机之间如何通信容器访问外部网络外部网络访问容器 k8s 网络模型CNIpod 网络配置流程 k8s 热门网络插件介绍Flannel 来源Calico 来源Cilium 来源 k8s 网络插件的工作模式Flannel 的工作模式Calico 的工作模式BGP 和…

Python 三种方式实现自动化任务

在这篇文章中&#xff0c;我们将介绍一些用Python实现机器人过程自动化的包。机器人流程自动化&#xff08;Robotic process automation&#xff0c;简称RPA&#xff09;是指将鼠标点击和键盘按压自动化的过程&#xff0c;即模拟人类用户的操作。RPA用于各种应用程序&#xff0…

时代变迁对传统机器人等方向课程的巨大撕裂

2020年之后&#xff0c;全面转型新质课程规划&#xff0c;传统课程规划全部转为经验。 农耕-代表性生产关系-封建分配制度主要生产力-人力工业-代表性生产关系-资本分配制度工业分为机械时代&#xff0c;电气时代&#xff0c;信息时代&#xff1b;主要生产力-人力转为人脑&…

流程图图解@RequestBody @RequestPart @RequestParam @ModelAttribute

RequestBody 只能用一次&#xff0c;因为只有一个请求体 #mermaid-svg-8WZfkzl0GPvOiNj3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8WZfkzl0GPvOiNj3 .error-icon{fill:#552222;}#mermaid-svg-8WZfkzl0GPvOiNj…

学习记录:js算法(九十九):冗余连接

文章目录 冗余连接思路一 冗余连接 树可以看成是一个连通且 无环 的 无向 图。 给定往一棵 n 个节点 (节点值 1&#xff5e;n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间&#xff0c;且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数…

ISUP协议视频平台EasyCVR私有化部署视频平台如何实现RTMP推流将大疆无人机的视频画面回传?

在现代视频监控和流媒体技术领域&#xff0c;EasyCVR视频融合云平台以其卓越的性能和灵活性&#xff0c;成为了跨区域、网络化视频监控综合管理的理想选择。作为TSINGSEE青犀视频“云边端”架构体系中的核心组件&#xff0c;私有化部署视频平台EasyCVR不仅能够实现视频数据的集…

【Linux】Linux入门实操——进程管理(重点)

1. 概述 在 LINUX 中&#xff0c;每个执行的程序都称为一个进程。每一个进程都分配一个ID号(pid,进程号)。>windows > linux每个进程都可能以两种方式存在的。前台与后台&#xff0c;所谓前台进程就是用户目前的屏幕上可以进行操作的。后台进程则是实际在操作&#xff0…

Postman之安装及汉化基本使用介绍

Postman之安装及汉化 1.安装及汉化postman2.基本使用介绍2.1.基本功能&#xff1a;2.2.编辑、查看、设置环境、全局、集合变量2.3.复制代码片段2.4.运行集合中的所有请求及引用外部文件进行参数化 1.安装及汉化postman 下载安装包 首先可以到官网下载安装包&#xff0c;需要注…

百度AI人脸检测与对比

1.注册账号 打开网站 https://ai.baidu.com/ &#xff0c;注册百度账号并登录 2.创建应用 3.技术文档 https://ai.baidu.com/ai-doc/FACE/yk37c1u4t 4.Spring Boot简单集成测试 pom.xml 配置&#xff1a; <!--百度AI--> <dependency> <groupId>com.baidu.…

基于Java Springboot川剧科普平台

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

用vscode编写verilog时,如何有信号定义提示、信号定义跳转(go to definition)、模块跳转(跨文件跳转)这些功能

&#xff08;一&#xff09;方法一&#xff1a;安装插件SystemVerilog - Language Support 安装一个vscode插件即可&#xff0c;插件叫SystemVerilog - Language Support。虽然说另一个插件“Verilog-HDL/SystemVerilog/Bluespec SystemVerilog”也有信号提示及定义跳转功能&am…

Debezium-EmbeddedEngine

提示&#xff1a;一个嵌入式的Kafka Connect源连接器的工作机制 文章目录 前言一、控制流图二、代码分析 1.构造函数2.完成回调3.连接器回调4.RUN总结 前言 工作机制&#xff1a; * 独立运行&#xff1a;嵌入式连接器在应用程序进程中独立运行&#xff0c;不需要Kafka、Kafka C…

ThreadLocal原理及其内存泄漏

ThreadLocal通过为每个线程创建一个共享变量的副本来保证各个线程之间变量的访问和修改互不影响。 ThreadLocal存放的值是线程内共享的&#xff0c;线程间互斥的&#xff0c;主要用于线程内共享数据&#xff0c;避免通过参数传递。 ThreadLocal有四个方法&#xff1a; initialV…

Java中日志采集框架-JUL、Slf4j、Log4j、Logstash

1. 日志采集 日志采集是指在软件系统、网络设备、服务器或其他IT基础设施中自动收集日志文件和事件信息的过程。这些日志通常包含了时间戳、事件类型、源和目标信息、错误代码、用户操作记录等关键数据。日志采集的目的是为了监控系统运行状态、分析系统性能、审计用户行为、故…

C++系列之继承

&#x1f497; &#x1f497; 博客:小怡同学 &#x1f497; &#x1f497; 个人简介:编程小萌新 &#x1f497; &#x1f497; 如果博客对大家有用的话&#xff0c;请点赞关注再收藏 &#x1f31e; 继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段&#xf…