当前位置: 首页 > news >正文

永不休眠:Linux 守护进程的工作原理

个人主页:chian-ocean

文章专栏-NET

永不休眠:Linux 守护进程的工作原理

    • 个人主页:chian-ocean
    • 文章专栏-NET
  • 前言
  • 进程信息字段含义
    • 进程组ID(`PGID`)
    • 会话ID(`SID`)
  • 前后台进程
    • 定义
      • 后台进程的特点
    • 前后台进程的操作
      • `jobs`显示后台作业
      • `fg`将后台作业带回前台
      • `bg`将后台作业带回前台
  • 守护进程
    • 守护进程的特点
    • 编写守护进程

前言

在 Linux 系统中,守护进程(Daemon)是指那些在后台运行的进程,通常不与用户直接交互,而是提供某种服务或者完成系统任务。守护进程通常在系统启动时启动,并在系统运行时持续存在。

在这里插入图片描述

进程信息字段含义

image-20250613220101763

字段含义用途示例
PPID父进程 ID表示当前进程的父进程的进程 ID。帮助追踪进程的父子关系。23449
PID进程 ID唯一标识当前进程。通过 PID 可以管理进程。24284
PGID进程组 ID标识当前进程所在的进程组。用于管理相关进程。24284
SID会话 ID标识当前进程所属的会话 ID。会话是共享同一个控制终端的进程集合。23449
TTY终端类型指当前进程所使用的终端设备。pts/0
TPGID控制终端的进程组 ID标识该进程所属的控制终端的进程组。24284
STAT进程状态表示进程当前的状态。常见状态包括休眠、运行、停止等。S+
UID用户 ID表示当前运行该进程的用户的标识符。1000
TIME进程占用的 CPU 时间显示该进程使用的 CPU 时间,格式为“分钟:秒”。0:00
COMMAND执行的命令显示当前进程正在执行的命令或程序。sleep 100

进程组ID(PGID

image-20250613220115253

  • PGID(进程组 ID) 表示进程所在的进程组的标识符。在该输出中,所有进程的 PGID 都是 25091,说明这些进程都属于同一个进程组。

  • 这个进程组的 leader(进程组长) 是 PID 25091(它的 PGID 值是它自己的 PID),也就是说,这个进程(PID 25091)是该进程组的领导者。该进程组中的其他进程(例如 PID 25092、25093)都是由该进程创建的,它们与进程组共享同一个 PGID

为什么 PGID 相同?

  • 进程组是一个将多个相关进程组织在一起的机制。在这个例子中,sleep 100 进程的多个实例(PID 25091、25092、25093)都属于同一个进程组,它们的 PGID 是相同的。
  • 这种设计允许操作系统同时管理多个进程,比如向整个进程组发送信号,进行进程组控制等。

会话ID(SID

image-20250613220119253

  • 在这里面我们创建了三个会话,SID 分别为 224492240325410分别控制着不同的终端( TTY

在此会话中我们执行

sleep 100 | sleep 100 | sleep 100 

image-20250613220122467

观察进程 sleep SID = 24003

  • 所有显示的 sleep 进程的 SID 都是 24003。这表明所有这些 sleep 进程属于同一个会话,即它们共享相同的会话 ID。
  • SID 表示这些进程是同一个会话中的进程,会话中的所有进程都具有相同的 SID

bash : 会话的领导者

  • 会话的 SID 通常等于会话的 leader(会话领导进程)的 PID。因此,SID = 24003 表明会话中的领导进程的 PID 是 24003。这个进程的 PID 会作为会话的 SID
  • 这些 sleep 进程的 SID24003,表明它们是由 PID = 24003 启动的进程所创建,并且它们共享该会话。

前后台进程

定义

  • 前台进程 是那些直接与用户交互并占用当前终端的进程,通常它们会接收用户输入并显示输出。
#include <iostream>                                                                     
#include <unistd.h>    using namespace std;    int main ()    
{    while(1)    {    cout << "hello proc "<<endl;    sleep(1);    }    return 0;    
}
  • 执行代码在前台进程,执行指令(./文件名):

image-20250613220127778

  • 后台进程 则是在后台运行的进程,它们不直接与用户交互,不占用终端,通常用于执行长时间运行的任务,如守护进程或定时任务。

  • 如果在后台进程的执行的指令就是:

./文件名 &

image-20250613220132041

后台进程的特点

  • 不占用终端:后台进程不会占用当前的控制终端(即用户的输入输出设备)。当你将一个进程放入后台运行时,终端仍然可以用来执行其他命令。

  • 不与用户交互:后台进程不直接与用户交互,因此它不会阻塞终端的使用。例如,你可以在后台运行一个长时间的下载任务,而继续在前台执行其他任务(如编辑文件、查看文件等)。

  • 异步执行:后台进程通常是异步执行的,即它们独立于当前正在运行的进程执行,不会干扰前台进程的执行

前后台进程的操作

jobs显示后台作业

image-20250613220135254

  • 当前证明有11个任务在同时跑。

fg将后台作业带回前台

fg -进程编号

image-20250613220343590

分析

  • 后台运行程序:执行了 ./a.out &,该命令将程序 a.out 在后台运行,并返回了进程号 [1] 27998,表示后台程序正在运行。
  • 查看输出:输入了 hello proc,终端多次显示了这个字符串,可能是 a.out 程序的输出内容。
  • 调到前台:使用 fg 1 将后台运行的程序(作业号 1)调到前台,使其开始在前台运行。此时可以看到程序输出持续显示。
  • 终止程序:按下 CTRL + C(中断信号),终止了在前台运行的程序。

bg将后台作业带回前台

bg -进程编号

image-20250613220347268

分析:

  • ./a.out:执行这个命令来运行已编译的程序 a.out。程序打印了三次 hello proc 到终端。

  • ^Z:这是一个键盘快捷键,用来暂停(停止)正在运行的程序。程序被挂起,并显示消息 [1]+ Stopped,表示该进程已暂停。

  • bg 1bg 命令用于将停止的进程(此处为作业号 1)恢复到后台继续运行。这样程序就可以继续执行,而不会占用终端。

  • ./a.out &:程序现在在后台运行,输出继续显示 hello proc

守护进程

守护进程(Daemon)是计算机中在后台运行的一个长期存在的进程,通常在操作系统启动时自动启动,并在系统关闭时停止。它不与用户直接交互,而是负责执行一些后台任务,如定时任务、系统监控、服务提供等。

守护进程的特点

  1. 后台运行:守护进程不与终端直接交互,它们在后台运行,并且不会因用户登出而终止。、
  2. 自启动和长期运行:大多数守护进程在系统启动时自动启动,并且通常会一直运行直到系统关闭或守护进程被手动停止。
  3. 与终端分离:守护进程通常会与终端或控制台分离,这意味着它们不依赖于任何终端会话,甚至在用户退出登录后也会继续运行。

编写守护进程

#pragma once  // 防止该头文件被多次包含#include <iostream>      // 引入输入输出流库
#include <unistd.h>      // 引入Unix标准函数库(比如fork, setsid等)
#include <string>        // 引入C++标准字符串库
#include <signal.h>      // 引入信号处理库(signal相关函数)
#include <sys/types.h>   // 包含系统数据类型(pid_t等)
#include <sys/stat.h>    // 引入文件状态和权限库
#include <fcntl.h>       // 引入文件控制库const std::string nullfile = "/dev/null";  // 定义一个常量 nullfile,表示 Unix 系统中的空设备文件 /dev/nullvoid daemon(const std::string chdir = "")
{// 忽略一些常见的信号signal(SIGCHLD, SIG_IGN);  // 忽略子进程结束信号(不需要等待子进程)signal(SIGPIPE, SIG_IGN);  // 忽略管道破裂信号signal(SIGSTOP, SIG_IGN);  // 忽略停止信号(通常用户发送的 Ctrl+Z)// 将当前进程变为独立会话的领导者if (fork() > 0){// 父进程退出,子进程继续exit(1);}setsid();  // 创建新的会话,脱离终端,成为会话领导者// 如果传入了工作目录路径,尝试更改目录权限if (!chdir.empty())chmod(chdir.c_str(), 0777);  // chmod 需要传递权限值参数,这里假设为 0777// 打开 /dev/null 设备文件,以只读方式打开int fd = open(nullfile.c_str(), O_RDONLY);if (fd > 0){// 将标准输入、输出和错误输出重定向到 /dev/nulldup2(0, fd);  // 将标准输入(fd 0)重定向到 /dev/nulldup2(1, fd);  // 将标准输出(fd 1)重定向到 /dev/nulldup2(2, fd);  // 将标准错误输出(fd 2)重定向到 /dev/nullclose(fd);    // 关闭文件描述符}
}
  • 忽略异常信号:守护进程通常不会干扰终端信号,因此忽略了与子进程、管道破裂和停止信号相关的信号。
  • 脱离终端:通过 fork()setsid() 创建一个新的会话,使得守护进程不再受控制终端影响。
  • 修改工作目录:尝试修改工作目录(但代码存在错误,应改为 chdir())。
  • 重定向输入输出:将标准输入、输出和错误输出重定向到 /dev/null,避免进程与终端交互。

相关文章:

  • 新一代python管理工具--uv
  • 戴尔 17G 服务器 E610 OCP千兆网卡驱动安装
  • 高频面试之11Flink
  • ar 导航导览技术如何实现的?室内外融合定位与ar渲染技术深度解析
  • 深入理解 PyTorch:从基础到高级应用
  • C#实战:解决NPOI读取Excel单元格数值0.00001显示为1E-05的问题
  • ROS2编译的理解,与GPT对话
  • 基于springboot旅游管理系统+源码+文档+视频
  • 优化 Excel 文件可以提升文件性能、减少文件大小并加快计算速度
  • 【 新能源汽车OBD网关全解析:原理、方案、测试与趋势】
  • 中科院1区|IF10+:加大医学系团队利用GPT-4+电子病历分析,革新肝硬化并发症队列识别
  • postman Access denied for user‘root‘@‘XXXXXXXX(using password: YES)
  • ubuntu 无法访问位置 error mounting 解决办法 双系统
  • Linux驱动学习day4
  • 第六章 进阶21 奶茶周会没了奶茶
  • 华为云Flexus+DeepSeek征文 | 基于Dify构建个人在线旅游助手
  • React Native【实战范例】水平滚动分类 FlatList
  • 提示词Prompts(1)
  • 【论文阅读笔记】ICLR 2025 | 解析Ref-Gaussian如何实现高质量可交互反射渲染
  • 【论文阅读笔记】CVPR2025 | 2D高斯溅射的几何-光照解耦:Ref-GS实现开放世界级真实渲染
  • 网站网站制作服务/数字营销课程
  • 怎么样做网站管理员/关键词排名怎么做好
  • 最新网站模板/安卓aso
  • 网站制作的管理/全球十大搜索引擎入口
  • 做鸭服务的网站或群/产品软文怎么写
  • 珠海市网站设计公司/百度搜索排行榜风云榜