【Linux网络编程】之守护进程

【Linux网络编程】之守护进程

  • 进程组
    • 进程组的概念
    • 组长进程
  • 会话
    • 会话的概念
    • 会话ID
  • 控制终端
    • 控制终端的概念
    • 控制终端的作用
    • 会话、终端、bash三者的关系
  • 前台进程与后台进程
    • 概念
    • 特点
    • 查看当前终端的后台进程
    • 前台进程与后台进程的切换
  • 作业控制
    • 相关概念
    • 作业状态(一般指后台作业)
  • 守护进程
    • 概念
    • 将进程守护化
      • 进程守护化的步骤
      • 代码实现

进程组

进程组的概念

当我们使用以下命令查与进程相关的属性时,会看到一个叫PGID的属性:

ps ajx

image-20250207143545861

它标识某一个进程属于哪个进程组。

进程组是一个进程或者多个进程的集合。每一个进程组有唯一的PGID,它是一个正整数,和PPIDPID一样,可以在C语言中用pid_t类型表示。

例如,在终端中执行如下命令:

sleep 1000 | sleep 2000 | sleep 3000

使用ps查看:

ps ajx | head -1 && ps ajx | grep -v 'grep' | grep sleep

img

这三个进程的PPID也就是父进程都是一样的,也就是-bash进程,所以这三个sleep进程是兄弟进程,它们同属于一个进程组。

image-20250207144949286

就算只有一个进程,它也会自成一个进程组:

image-20250207145100828

组长进程

组长进程就是进程组中的第一个创建的进程(按照时间),如果这个进程组中就只有一个进程,那么它就是进程组中的组长。

当进程组中的组长终止后,这个进程组并不会终止,要等到这个进程组中的最后一个进程终止,它才会终止。

代码验证1:使用下面代码先验证,C语言fork子进程,父进程和子进程属于一个进程组,且父进程是组长进程。

#include<stdio.h>
#include<unistd.h>
int main()
{
   pid_t id = fork();
   if(id == 0)//子进程执行
   {
        while(1)
        {
            printf("i am child,my pid is %d\n",getpid());
            sleep(1);
        }
   }

   while(1);
   return 0;
}

运行结果:

image-20250207150717602

代码验证2:当组长进程结束,进程组并不会立即终止,而是等这个组中所有的进程终止后再终止:

#include<stdio.h>
#include<unistd.h>
int main()
{
   pid_t id = fork();
   if(id == 0)//子进程执行
   {
        while(1)
        {
            printf("i am child,my pid is %d\n",getpid());
            sleep(1);
        }
   }

   return 0;
}

运行结果:

image-20250207151249008

会话

会话的概念

会话可以看作是多个进程组的集合,一个会话会有多个进程组,会话也会有唯一的会话ID。

一般来说,会话中的第一个进程组是-bash对应的进程组,会话ID等于该-bash进程组的组ID。

image-20250207153415886

通常来说,进程组可以由以下方式创建:

  1. 通过管道创建兄弟进程,这些兄弟进程是一个进程组
  2. 父进程fork子进程,父子进程是一个进程组。

会话ID

上面我们提到了会话ID,会话ID就是该会话中首进程的进程ID或者说是首进程的组ID。(就是-bash进程的进程ID,-bash进程总是会首进程,也是会首进程的组长进程)。

控制终端

控制终端的概念

在Linux/类Uinx系统中,控制终端通常与会话关联。即一个会话对应一个控制终端

当用户通过一个终端登录系统,会得到一个首进程shell进程,这个终端成为shell进程的控制终端,由于有关控制终端的信息存储在进程PCB中,后续的其它进程都是通过shell进程fork的,所以其它进程的控制终端也都是这个控制终端。

实际上控制终端是一个逻辑概念,每个控制终端都对应一个终端文件。这些文件被称为终端文件tty设备文件

Linux中,终端文件在/dev/pts路径下:

ls /dev/pts

实验验证:实验步骤如下。

  1. 终端1,循环执行以下脚本指令:

     while :;do ls -l /dev/pts;sleep 1;echo "~~~~~~~~~~~~~~~~~";done
    
  2. 不断创建新的终端,观察打印的终端文件是否增多。

  3. 关闭打开的终端,观察打印的终端文件是否减少。

实验现象如下:

屏幕录制-2025-02-07-172050

控制终端的作用

  1. 信号发送:可以通过特定的组合键向前台进程组发送信号,比如Ctrl+C发送SIGINT信号来中断当前操作,或者Ctrl+Z发送SIGTSTP暂停一个进程。

  2. 输入输出:控制终端为进程提供标准输入、输出和错误流。大多数情况下,这些流直接对应于用户的键盘输入和屏幕显示。

    • 什么意思呢,就是我们向键盘输入一个内容都会显示在控制终端上,printf等往显示器打印的函数,打印的内容也会显示到终端上。因为**当进程启动时,如果没有特别指定其他的输入输出目的地(重定向),其标准输入、输出和错误流默认就会关联到控制终端对应的设备文件上。**云服务器上文件描述符012指向的文件:

      image-20250207173240326

    • 虚拟机中(也类似):

      image-20250207174036657

  3. 作业控制:允许用户管理属于当前shell会话的不同任务(作业)。这包括将作业放到后台执行或从前台恢复执行。作业和前台后台进程的概念我们稍后会谈。

会话、终端、bash三者的关系

Linux中的shell进程叫做bash,当用户通过xshell等ssh远程登录客户端中的终端登录后,这个终端成为bash进程的控制终端,而这个终端中的所有进程组(前台和后台)构成一个会话(当你登录系统并启动bash时,实际上就开启了一个新的会话。),画图来表示就是下面这样:

image-20250207181459757

前台进程与后台进程

概念

前台进程和后台进程都是进程,唯一区别就是前台进程可以通过终端接收用户的输入,同时也可以接收来自用户的命令(ctrl Cctrl Z),前台进程还可以将输出输入到显示器(也就是终端上)。但是后台进程则不同,它不直接与用户交互,即它们不接受键盘输入,也不将输出直接显示给用户(除非特别配置)。

特点

  1. 前台进程
    • 独占性:同一终端,同一时刻,只能有一个进程或进程组。这意味着前台进程对输入输出有独占性。
    • 用户交互:前台进程可以直接通过终端与用户进行交互。这意味着它可以接受用户的输入,并将其显示在屏幕上。通常用户输入的命令,就是在前台运行。
    • 信号响应:前台进程组可以接收到某些类型的信号,比如通过按下Ctrl+C发送的SIGINT中断信号来终止当前操作。这是前台进程的一个重要特性,允许用户直接控制正在运行的程序。
  2. 后台进程
    • 并发执行:多个后台进程可以同时执行(并发是看似同时执行,实则轮询执行),一个终端可以有多个后台作业同时执行。
    • 无需与用户交互:不接收用户的输入,也不会将输出直接显示给用户。
    • 信号限制ctrl C等命令无法作用于后台进程,要使用killkillall等命令。

查看当前终端的后台进程

命令jobs可以查看当前终端的后台进程,它会显示每个后台作业的作业号和状态。

jobs

选项-l:添加 -l 选项后,jobs 命令不仅显示基本的作业信息,还会额外列出每个作业的进程ID(PID)。

前台进程与后台进程的切换

  1. 前台进程切换为后台进程

    • 方法1:在执行一个程序时,在后面加上&

      image-20250207183742115

    • 方法2ctrl Z暂停某个正在执行的前台进程,它将被切为后台进程:

      image-20250207184541663

    • 方法3:当某个子进程的父进程结束,它还在运行时它就会变成孤儿进程。无法通过ctrl C命令终止它的运行,因为孤儿进程被initSIDPID为1)进程收养,但可以通过killkillall命令终止它。可以认为这是一种特殊情况。

  2. 后台进程切换为前台进程

    • 使用命令fg(foreground的缩写)将后台进程切换为前台进程:

      fg 作业号
      

      image-20250207193051184

    • 扩展命令bg,这个命令可以将暂停的命令继续在后台运行。

      bg
      

    `
    image-20250207193909521

作业控制

相关概念

作业

作业是指Linux系统中正在运行的一个进程或者进程组(多个进程)。进程之间一般通过管道来互相协作。

作业控制

shell可以同时运行一个前台作业和多个后台作业,这叫做作业控制。前台作业和后台作业都可以由多个进程组成。

作业号

作业号是后台作业专有的,它们在开始执行时或者执行完后会返回一个作业号。

示例1

echo "1111" &

image-20250208174913663

示例2

sleep 1000 | sleep 2000 | sleep 3000 &

image-20250208175050370

  • [1]就是该作业的作业号。

作业状态(一般指后台作业)

常见的作业有以下状态:

作业状态含义
正在运行(Running)后台作业(&),正在运行
暂停运行(Stopped)前台作业被ctrl z(或者是后台作业被相应的信号所暂停)暂停了
完成(Done)后台作业已完成执行(返回的状态码为0)
完成(Done(code))后台作业完成执行(返回的状态码非0)
终止(Terminated)后台作业被终止
  1. Running状态:

    image-20250208180841505

  2. Stopped状态:

    image-20250208181403878

  3. Done状态:

    image-20250208181451788

  4. Terminated状态:

    image-20250208181651879

  5. Done(code)状态。后台执行下面的脚本文件:

    exit 42 # 返回退出状态码42
    

    image-20250208182301269

守护进程

概念

守护进程不同于普通的后台进程(作业),普通的后台作业它有关联的终端,即使不与用户交互或者不输出内容到用户的显示器上,但是守护进程有自己独立的会话,并且它无终端关联,脱离终端控制,除非系统关闭,否则守护进程不会轻易的关闭。

常见的守护进程:比如httpd(Apache HTTP服务器)、sshd(SSH服务器)、crond(定时任务调度器)等都是典型的守护进程,它们为系统提供核心服务。

普通后台程序:例如,你在终端中运行的一个长时间的数据处理脚本,并在其后加上&让它在后台运行。这个脚本就是一个普通的后台程序,而不是守护进程。

将进程守护化

进程守护化的步骤

  1. 父进程fork子进程:让父进程退出,后续都是子进程来执行相关程序,并成为守护进程,因为创建一个新的会话需要该进程不是进程组的组长。这是系统设计所决定的,如果不这样做,会有循环依赖问题。
  2. setsid() 创建新会话:使子进程成为新会话的领导者,并脱离所有终端的控制,确保它没有控制终端。
  3. 改变当前工作目录(如果需要):通常是切换到根目录(/),以避免占用挂载点。
  4. 重定向标准输入、输出和错误流(如果后面不使用也可以关闭):通常指向/dev/null或其他适当的日志文件,以防止无意中使用这些默认流。/dev/null文件读取都会读到null,写入都会被自动丢弃。
  5. 关闭不需要的文件描述符:确保除了必要的资源外,其他文件描述符都被关闭。

代码实现

#include<stdio.h>
#include<unistd.h>
#include<stdbool.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>

const char* newdir = "/";
const char* newpath = "/dev/null";
void Demon(bool IsChangeWorkDir,bool IsRedir)
{
   //0.忽略可能引起程序异常的信号
   // 忽略SIGCHLD信号,防止产生僵尸进程
    signal(SIGCHLD, SIG_IGN);
   // 忽略SIGPIPE信号,避免程序因写入已关闭的pipe/socket而终止
    signal(SIGPIPE, SIG_IGN);
   //1.创建子进程,并让父进程退出
   if(fork() > 0)
   {
      printf("pid is %d\n",getpid());
      exit(0);
   }
   //2.让子进程新建一个会话,成为守护进程,子进程成为新会话的leader进程,会话ID和这个子进程的进程ID相同
   setsid();

   //3. 已经成为守护进程,查看是否需要更改工作目录
   if(IsChangeWorkDir)
   {
      chdir(newdir);
   }

   //4.查看是否需要重定向0、1、2标准输入、输入、错误流
   if(IsRedir)
   {
      int fd = open(newpath,O_RDWR);//以读写模式打开
      dup2(fd,0);
      dup2(fd,1);
      dup2(fd,2);
      close(fd);//不需要fd了
   }

   else
   {
      close(0);
      close(1);
      close(2);
   }
}
int main()
{
   Demon(true,true);
   while(true);//变成守护进程了
   return 0;
}

运行结果:

image-20250208193403430

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JS宏进阶:XMLHttpRequest对象

一、概述 XMLHttpRequest简称XHR&#xff0c;它是一个可以在JavaScript中使用的对象&#xff0c;用于在后台与服务器交换数据&#xff0c;实现页面的局部更新&#xff0c;而无需重新加载整个页面&#xff0c;也是Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;…

怎么查看电脑显存大小(查看电脑配置)

这里提供一个简单的方法查看 winr打开cmd 终端输入dxdiag进入DirectX 点击显示查看设备的显示内存&#xff08;VRAM&#xff09; 用这个方法查看电脑配置和显存是比较方便的 dxdiag功能 Dxdiag是Windows的DirectX诊断工具&#xff0c;其主要作用包括但不限于以下几点&#…

优惠券平台(一):基于责任链模式创建优惠券模板

前景概要 系统的主要实现是优惠券的相关业务&#xff0c;所以对于用户管理的实现我们简单用拦截器在触发接口前创建一个单一用户。 // 用户属于非核心功能&#xff0c;这里先通过模拟的形式代替。后续如果需要后管展示&#xff0c;会重构该代码 UserInfoDTO userInfoDTO new…

【机器学习】数据预处理之scikit-learn的Scaler与自定义Scaler类进行数据归一化

scikit-learn的Scaler数据归一化 一、摘要二、训练数据集和测试数据集的归一化处理原则三、scikit-learn中的Scalar类及示例四、自定义StandardScaler类进行数据归一化处理五、小结 一、摘要 本文主要介绍了scikit-learn中Scaler的使用方法&#xff0c;特别强调了数据归一化在…

机器学习中过拟合和欠拟合问题处理方法总结

目录 一、背景二、过拟合(Overfitting)2.1 基本概念2.2 过拟合4个最主要的特征2.3 防止过拟合的11个有效方法 三、欠拟合&#xff08;Underfitting&#xff09;3.1 基本概念3.2 欠拟合的4个特征3.3 防止欠拟合的11个有效方法 四、总结五、参考资料 一、背景 在机器学习模型训练…

ABP框架9——自定义拦截器的实现与使用

一、AOP编程 AOP定义:面向切片编程&#xff0c;着重强调功能&#xff0c;将功能从业务逻辑分离出来。AOP使用场景&#xff1a;处理通用的、与业务逻辑无关的功能&#xff08;如日志记录、性能监控、事务管理等&#xff09;拦截器:拦截方法调用并添加额外的行为&#xff0c;比如…

基于YoloV11和驱动级鼠标模拟实现Ai自瞄

本文将围绕基于 YoloV11 和驱动级鼠标实现 FPS 游戏 AI 自瞄展开阐述。 需要着重强调的是&#xff0c;本文内容仅用于学术研究和技术学习目的。严禁任何个人或组织将文中所提及的技术、方法及思路应用于违法行为&#xff0c;包括但不限于在各类游戏中实施作弊等违规操作。若因违…

示例代码:C# MQTTS双向认证(客户端)(服务器EMQX)

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

记录IMX6ULL开发板上移植SQLite3并运行Qt程序

文章目录 概要移植SQLite3Qt程序部署实验现象 概要 基于上一章对使用Qt运行对应的实验实例来完成对用户使用ui界面完成对SQLite数据库的增删改查等操作。本文旨在对上一句节的Qt程序部署到IMX6ULL开发板&#xff0c;并且完成对SQLite数据库在IMX6ULL开发板上的移植。 移植SQ…

达梦数据库(DM)线程管理

目录标题 达梦数据库&#xff08;DM&#xff09;线程管理笔记一、DM 线程架构概述二、DM 主要线程类型及功能&#xff08;一&#xff09;监听线程&#xff08;二&#xff09;工作线程&#xff08;三&#xff09;IO 线程&#xff08;四&#xff09;调度线程&#xff08;五&#…

02.10 TCP之文件传输

1.思维导图 2.作业 服务器代码&#xff1a; #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> …

Node.js 环境配置

什么是 Node.js Node.js 是一个基于 Chrome V8 JavaScript 引擎的 JavaScript 运行时环境&#xff0c;它允许你在服务器端运行 JavaScript。传统上&#xff0c;JavaScript 主要用于浏览器中的前端开发&#xff0c;而 Node.js 使得 JavaScript 也能够在服务器上执行&#xff0c;…

【办公类-53-04】20250209Python模仿制作2024学年第二学期校历

背景需求&#xff1a; 马上开学了&#xff0c;又要制作校历&#xff08;删划节假日&#xff09;。之前我都是用网络的图片&#xff0c;然后在PPT里修改。 存在问题&#xff1a; 网络校历是从周日开始的&#xff0c;但日常我们老师做教案&#xff0c;都是默认从周一到周五&…

KERL文献阅读分享:知识图谱与预训练语言模型赋能会话推荐系统

标题期刊年份Knowledge Graphs and Pre-trained Language Models enhanced Representation Learning for Conversational Recommender SystemsJournal of LaTeX Class Files2021 &#x1f4c8;研究背景 在数字时代&#xff0c;个性化推荐系统已经成为了我们生活的一部分。从电…

强一致性算法:Raft

目录 什么是 Raft 算法&#xff1f; Leader的选举 投票分裂后的选举过程 Raft算法日志复制过程 修复不一样的日志 数据安全性的保证 什么是 Raft 算法&#xff1f; Raft 算法是一种是一种用于管理复制日志的强一致性算法&#xff0c;用于保证分布式系统中节点数据的一致…

[MyabtisPlus]PG的TIMESTAMPTZ不支持转换为LocalDateTime

背景 数据库用的是PG&#xff0c;且created_time字段用的是带时区的timestamptz类型&#xff1a; 用MyabtisPlus(MP)的的代码生成&#xff0c;默认生成的是JDK8的LocalDateTime类型&#xff1a; 结果&#xff0c;在查询时候&#xff0c;无法做到实体类的类型自动转换&#xff0…

cliproxy代理服务使用指南

Cliproxy代理服务使用指南 一、引言 Cliproxy&#xff0c;作为一款高效稳定的代理服务工具&#xff0c;广泛应用于跨境电商、数据分析、网络爬虫、远程办公等领域。本指南旨在帮助用户快速上手Cliproxy&#xff0c;充分利用其代理服务&#xff0c;提升工作效率与数据安全。 二、…

【Java 面试 八股文】Redis篇

Redis 1. 什么是缓存穿透&#xff1f;怎么解决&#xff1f;2. 你能介绍一下布隆过滤器吗&#xff1f;3. 什么是缓存击穿&#xff1f;怎么解决&#xff1f;4. 什么是缓存雪崩&#xff1f;怎么解决&#xff1f;5. redis做为缓存&#xff0c;mysql的数据如何与redis进行同步呢&…

防火墙术语大全( Firewalld Glossary of Terms)

防火墙术语大全 防火墙作为网络安全中不可或缺的设备&#xff0c;在各种网络架构中扮演着至关重要的角色。无论是企业级防火墙、云防火墙还是家用路由器内置的防火墙&#xff0c;它们的工作原理和配置策略都离不开一系列专业术语的支撑。对于网络工程师来说&#xff0c;掌握这…

【蓝耘元生代智算云平台】一键部署 DeepSeek人工智能模型

欢迎来到ZyyOvO的博客✨&#xff0c;一个关于探索技术的角落&#xff0c;记录学习的点滴&#x1f4d6;&#xff0c;分享实用的技巧&#x1f6e0;️&#xff0c;偶尔还有一些奇思妙想&#x1f4a1; 本文由ZyyOvO原创✍️&#xff0c;感谢支持❤️&#xff01;请尊重原创&#x1…