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

【Linux】守护进程与作业控制:进程组、会话与控制终端

文章目录

  • 1. 进程组
    • ① 组长进程
  • 2. 会话
    • ① 概念
    • ② 创建会话
  • 3. 控制终端
  • 4. 作业控制
    • ① 概念
    • ② 作业号 与 jobs命令
    • ③ 作业状态
    • ④ 作业 挂起 与 切回
    • ⑤ 作业相关信号
    • ⑥ 功能理解
    • ⑦ 通过代码 将服务守护进程化

1. 进程组

对于一个进程来说,自身一定含有一个PID(进程ID),且一定属于某个进程组;进程组是一个或者多个进程的集合, 一个进程组可以包含多个进程

每个进程组有唯一的进程组ID(PGID), 类似于PID, 是一个正整数, 可以存放在 pid_t 数据类型·中;

比如对于下面的例子,
在这里插入图片描述

显示的信息分别是:PID PGID PPID COMMAND


① 组长进程

每一个进程组都有一个组长进程,且组长进程的ID就是组ID,例如通过下面的ps命令可以查看组长进程,可以看出PGID = 24802 = bash 的PID;该进程组包括ps 与 cat 两个进程(bash为组长进程)

wqy@wqy-virtual-machine:~/$ ps -o pid,pgid,ppid,comm | cat
    PID    PGID    PPID COMMAND
  24802   24802    2658 bash
  25773   25773   24802 ps
  25774   25773   24802 cat
  • 进程组组长的作用: 进程组组长可以创建一个进程组或创建该组的进程
  • 进程组的生命周期: 从进程组创建开始到其中最后一个进程离开为止。 注意:

只要某个进程组中有一个进程存在, 则该进程组就存在, 这与其组长进程是否已经终止无关;


2. 会话

① 概念

在我们使用ps命令查看进程状态时,会有一个SID,即会话ID,什么是会话?

会话可以看作是一个或多个进程组的集合, 一个会话可以包含多个进程组。 每一个会话也有一个会话 ID(SID)

在这里插入图片描述

通常可以通过管道将几个进程编成一个进程组。

下面我们利用管道将几个sleep进程 编程一个进程组:

# & 表示将进程在后台运行
wqy@wqy-virtual-machine:~$ sleep 100 | sleep 200 | sleep 300 &

随后进行查询:

wqy@wqy-virtual-machine:~$ ps axj | grep sleep | grep -v grep
PPID       PID     PGID     SID   TTY       TPGID      STAT   UID   TIMECOMMAND
   4908   44378    4908    4908 ?             -1 S     1000   0:00 sleep 180
  44663   44713   44713   44663 pts/0      44782 S     1000   0:00 sleep 100
  44663   44714   44713   44663 pts/0      44782 S     1000   0:00 sleep 200
  44663   44715   44713   44663 pts/0      44782 S     1000   0:00 sleep 300

② 创建会话

如何创建会话?可以调用 setseid 函数来创建一个会话, 前提 调用进程不能是组长进程。

#include <unistd.h>
/*
*功能: 创建会话
*返回值: 创建成功返回 SID, 失败返回-1
*/
pid_t setsid(void);

对于这个sid,即会话ID,可以理解为,会话中 的首进程ID(也即会话首进程的组长ID)

调用该接口函数后会发生:

  • 调用进程会变成新会话的会话首进程。此时 新会话中只有一个进程;
  • 调用进程变为进程组组长。 新进程组 ID 就是当前调用进程 ID(组长进程ID)
  • 该进程未控制终端。 如果在调用 setsid 之前该进程存在控制终端, 则调用之后会切断联系;

需要注意:如果调用进程本身是进程组组长, 调用setsid接口 会报错, 为了避免错外情况, 一般先调用 fork 创建子进程, 父进程终止, 子进程继续执行, (子进程会继承父进程的进程组 ID, 新分配进程 ID), 就不会出现报错;


3. 控制终端

在 UNIX 系统中,用户通过终端登录系统后,会得到一个 Shell 进程。该终端被称为 Shell 进程的控制终端。控制终端的信息保存在 进程控制块(PCB) 中。由于使用 fork 创建进程会复制 PCB 中的信息,因此由 Shell 进程启动的其他进程也会将该终端作为它们的控制终端。


默认情况下,没有进行重定向的情况下,每个进程的:

  • 标准输入(stdin)
  • 标准输出(stdout)
  • 标准错误(stderr)

都指向控制终端。具体来说:

  • 进程从标准输入读取数据,这通常是用户的键盘输入。
  • 进程向标准输出或标准错误输出写入数据,这通常是输出到显示器上。

此外,控制终端与 会话进程组 及其他一些概念密切相关:

  1. 会话和控制终端

    • 一个会话可以有一个控制终端。通常,会话首进程打开一个终端(终端设备或伪终端设备)后,该终端就成为该会话的控制终端
  2. 控制进程

    • 建立与控制终端连接的会话首进程被称为 控制进程
  3. 进程组

    • 一个会话中的多个进程组可被分为一个前台进程组以及一个或多个后台进程组:
      • 如果一个会话有一个控制终端,则它有一个前台进程组,而会话中的其他进程组则为后台进程组。
      • 无论何时在终端输入中断键(Ctrl + C)或退出键(**Ctrl + **),都会将中断信号发送给前台进程组的所有进程
      • 如果终端接口检测到调制解调器(或网络)已经断开,则将挂断信号发送给控制进程(会话首进程)。

上述关系可以用下图表述:

在这里插入图片描述


4. 作业控制

① 概念

什么是作业控制(Job Control)

  • 作业定义作业是用户为完成特定任务而启动的进程集合。一个作业可以由单个进程或多个进程组成,这些进程通过协作来完成任务,通常以管道形式连接。

  • 前后台作业

    • 前台作业:可以由多个进程组成,用户与其交互。
    • 后台作业:也可以由多个进程组成,用户可以继续执行其他操作。
  • Shell 的作业控制:Shell 控制的是作业或进程组,而非单个进程。它可以同时运行一个前台作业和任意多个后台作业。

命令就是一个包含两个命令的前台作业:(两个进程通过管道连接)

cat /test/test.cpp | head -n 5

② 作业号 与 jobs命令

放在后台执行的程序或命令称为后台命令。 在命令的后面加上 & 符号,令 Shell 识别为后台命令。例如:

sleep 30 &
  • 后台命令执行时,用户无需等待该命令完成,可以立即输入新的命令。
  • 当后台进程执行完毕后,Shell 会返回一个作业号和进程号(PID)。

对于上面的命令,会有一下输出:

[1] 12345     #其中 `[1]` 是作业号,`12345` 是进程号(PID)

我们可以通过 jobs 命令查看当前用户后台执⾏或挂起的作业:

jobs # -p表示只显示PID -l表示显示详细信息

我们分别在前台与后台创建作业,并使用jobs命令进行查看:

wqy@wqy-virtual-machine:~/warehouse/test$ jobs -l
[1]+  3575 Stopped                 sleep 100
[2]-  3622 Running                 sleep 100 &

作业号后的符号表示:

  1. + : 表示该作业号是默认作业
  2. -: 表示该作业即将成为默认作业
  3. 无符号: 表示其他作业

③ 作业状态

根据上面使用jobs执行结果:

常见的作业状态有:

状态描述
运行中进程正在执行中。
就绪进程已准备好执行,但等待 CPU 分配。
阻塞进程因等待某些资源(如 I/O)而暂停。
暂停进程被暂停,通常由用户发送停止信号(如 Ctrl + Z)。
后台进程在后台运行,不与终端交互。
完成进程执行完毕,已退出。
僵尸进程已终止,但仍保留在系统中,以便父进程读取其退出状态。

④ 作业 挂起 与 切回

我们在执行某个作业时, 可以通过 Ctrl+Z 键将作业挂起, 然后 Shell 会显示相关的作业号、 状态以及所执行的命令信息

比如:

wqy@wqy-virtual-machine:~/warehouse/test$ ./test
Process ID: 3883
^Z
[2]+  Stopped                 ./test
  • 可以通过 fg 命令将挂起的作业切回,, fg 后的参数可以为作业号或作业的命令名称。 如果参数缺省会默认将作业号为 1 的作业切到前台来执行;
  • 若当前系统只有一个作业在后台进⾏, 则可以直接使用 fg 命令不带参数直接切回。
参数描述
%<作业号>将指定作业号的后台作业带到前台。例如:fg %1
%<作业名称>将指定名称的作业带到前台。例如:fg %job_name
%%%+最近提交的作业
%-倒数第二个提交的作业
无参数默认将最后一个后台作业带到前台。

⑤ 作业相关信号

信号描述
SIGINT中断信号,通常由 Ctrl + C 发送,终止进程。
SIGQUIT退出信号,通常由 Ctrl + \ 发送,终止进程并生成核心转储。
SIGTSTP停止信号,通常由 Ctrl + Z 发送,暂停进程。
SIGCONT继续信号,用于恢复被暂停的进程。
SIGTERM终止信号,请求进程优雅地终止。
SIGKILL强制终止信号,无法被捕获或忽略,立即终止进程。

⑥ 功能理解

终端的 I/O(标准输入和标准输出)和信号确实与前台进程组密切相关。当一个进程在前台运行时,它会接收来自终端的输入和输出,以及来自终端的信号(如 SIGINT 和 SIGTSTP)。如果进程被置于后台,它将无法接收这些信号和输入,由下图可以观察作业控制的功能:
在这里插入图片描述

⑦ 通过代码 将服务守护进程化

我们通过下面的代码可以将一个会话 守护进程化:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <fstream>
#include <fcntl.h>

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

// 守护进程化
void Daemonize(bool ischdir, bool isclose) {
    // 1. 忽略部分终端信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    if(fork() > 0) {
        std::cout << "父进程退出......" << std::endl;
        exit(0);
    }

    // 子进程
    setsid(); // 创建新会话; 子进程成为新的会话组长
 
    if(ischdir) {
        chdir(root); // 改变工作目录为根目录
    }

    // 关闭标准输入、输出、错误
    if(isclose) {
        close(0);
        close(1);
        close(2);
    } else {
        // 一般进行重定向即可
        int fd = open(dev_null, O_RDWR);
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }
}

有了这个功能,当执行一些需要持续运行且不需要作为前台进程的进程时,可以将其守护进程化,比如 web 服务器、数据库服务、打印服务 等;


http://www.kler.cn/news/365204.html

相关文章:

  • 基于Multisim的四人智力竞赛抢答器设计与仿真
  • Android13、14特殊权限-应用安装权限适配
  • Go语言中三个输入函数(scanf,scan,scanln)的区别
  • 牛客网面试题—分割字符串JS写法
  • 轻松检测麦克风功能:使用Python的sounddevice和soundfile库
  • 论文阅读与写作入门
  • micro-app【微前端实战】主应用 vue3 + vite 子应用 vue3+vite
  • 【Python】相等性比较运算(==, is)的学习笔记
  • 认识ldconfig,不仅仅可以用于查看库的版本
  • 力扣143:重排链表
  • 高可用之限流 09-guava RateLimiter 入门使用简介 源码分析
  • Linux系统下kazam生成的.mp4文件无法用window打开
  • 学习游戏测试需要掌握哪些基础技术?
  • django5入门【01】环境配置
  • 五大场景实践 深度解读指标平台业务价值
  • ffmpeg视频滤镜:平均模糊
  • 【系统架构设计师】一、绪论
  • 第五届光学与图像处理国际学术会议(ICOIP 2025)征稿中版面有限!
  • Android——应用安装
  • Paramiko实现SSH自动化实战教程
  • 2024-09学习笔记
  • TCP/UDP 通用通信代码库(C语言实现)
  • java高性能处理10G大文件
  • 使用Vue.js构建响应式Web应用
  • [DB] NSM
  • 【python openai function2json小工具】