进程间关系与守护进程

news2024/12/24 16:53:38

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

进程间关系与守护进程

收录于专栏[Linux学习]
本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

1. 进程组

什么是进程组

组长进程

2. 会话

什么是会话

如何创建会话 

会话 ID(SID) 

3. 控制终端

4. 作业控制

什么是作业和作业控制?

作业号 

作业状态 

​作业的挂起与切回 

作业挂起 

作业切回 

查看后台执行或挂起的作业 

作业控制相关的信号 

5. 守护进程


1. 进程组

什么是进程组

之前我们提到了进程的概念,其实每一个进程除了有一个进程 ID(PID)之外,还属于一个进程组。进程组是一个或者多个进程的集合,一个进程组可以包含多个进程。每一个进程组也是有唯一的进程组 ID(PGID),并且这个 PGID 类似于进程 ID,同样是一个正整数,可以存放在 pid_t 数据类型中。 

-e:选项表示 every 的意思,表示输出每一个进程信息

-o:选项以逗号操作符(,)作为定界符,可以指定要输出的列

组长进程

每一个进程组都有一个组长进程。组长进程的 ID 等于其进程 ID。我们可以通过 ps 命令看到组长进程的现象:

从结果上看 ps 进程的 PID 和 PGID 相同,那就是说明 ps 进程是该进程组的组长进程,该进程包括 ps 和 cat 两个进程。

进程组组长的作用:进程组长可以创建一个进程组或者创建该组中的进程

进程组的声明周期:从进程组创建开始到其中最有一个进程离开为止。

注意:某个进程中有一个进程存在,则该进程组就存在,这与其组长进程是否已经终止无关。

2. 会话

什么是会话

刚刚我们谈到了进程组的概念,那么会话又是什么呢?会话其实和进程组息息相关,会话可以看成是一个或多个进程组的集合,一个会话可以包含多个进程。每一个会话也有一个会话 ID(SID)

通常我们都是使用 管道 将几个进程编程一个进程组。如上如所示进程组2和进程组3可能是由下列命令形成的:

proc2 | proc3 &
proc4 | proc5 | proc6 &

我们举一个例子观察一下这个现象:

a 选项表示不仅当前用户的进程,也列出所有其他用户的进程

x 选项表示不仅列出有控制终端的进程,也列出所有无控制终端的进程

j 选项表示列出与作业控制相关的信息,作业控制后续再说

grep 的 -v 选项表示反向过滤,即不过滤带有 grep 字段相关的进程

从上述结果来看 3 个进程对应的 PGID 相同,即属于同一个进程组。  

如何创建会话 

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

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

该接口调用之后会发生:

1. 调用进程会变成新会话的会话首进程。此时,新会话只有唯一的一个进程

2. 调用进程会变成进程组组长。新进程组 ID 就是当前调用进程 ID

3. 该进程没有控制终端。如果在调用 setsid 之前该进程存在控制终端,则调用之后会切断联系

需要注意的是:这个接口如果调用进程是进程组组长,则会报错,为了避免这种情况,我们通常的使用方法是先调用 fork 创建子进程,父进程终止,子进程继续执行,因为子进程会继承父进程的进程组 ID,而进程 ID 则是新分配的,就不会出现错误的情况。 

会话 ID(SID) 

上边我们提到了会话 ID,那么会话 ID 是什么呢?我们可以先说一下会话首进程,会话首进程是具有唯一进程 ID 的单个进程,那么我们可以将会话首进程的 ID 当做是会话 ID。注意:会话 ID 在有些地方也被称为 会话首进程的进程组 ID,因为会话首进程总是一个进程组的组长进程,所以两者是等价的。 

3. 控制终端

先说一下什么是控制终端?

在 UNIX 系统中,用户通过终端登录系统后得到一个 Shell 进程,这个终端称为 Shell 进程的控制终端。控制终端是保存在 PCB 中的信息,我们知道 fork 进程会复制 PCB 中的信息,因此 Shell 进程启动的其他进程的控制终端也是这个终端。 默认情况下没有重定向,每个进程的标准输入、标准输出和标准错误都指向控制终端,进程从标准输入读也就是读用户的键盘输入,进程往标准输出或标准错误输出写也就是输出到显示器上。另外会话、进程组以及控制终端还有一些其他的关系,我们在下边详细介绍:

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

建立与控制终端连接的会话首进程被称为控制进程。

一个会话中的几个进程组可以分成一个前台进程组以及一个或者多个后台进程组

如果一个会话有一个控制终端,则它有一个前台进程组,会话中的其他进程组则为后台进程组的所有进程。

如果终端接口检测到调制解调器(或网络)已经断开,则将挂断的信号发送给这些特性的关系如下图所示:

 

4. 作业控制

什么是作业和作业控制?

作业是针对用户来讲,用户完成某项任务而启动的进程,一个作业既可以只包含一个进程,也可以包含多个进程,进程之间互相协作完成任务,通常是一个进程管道。

Shell 分前后台控制的不是进程而是作业 或者进程组。一个前台作业可以由多个进程组成。一个后台作业也可以由多个进程组成,Shell 可以同时运行一个前台作业和任意多个后台作业,这称为作业控制 

例如下列命令就是一个作业,它包括两个命令,在执行时 Shell 将在前台启动由两个进程组成的作业:

cat /etc/filesystems | head -n 5

作业号 

放在后台执行的程序或命令称为后台命令,可以在命令的后面加上 & 符号从而让 Shell 识别这是一个后台命令,后台命令不用等待该命令执行完成,就可立即接收新的命令,另外后台进程执行完后会返回一个作业号以及一个进程号(PID)。 

例如 下面的命令在后台启动了一个作业,该作业由两个进程组成,两个进程都在后台运行:

cat /etc/filesystems | grep ext &

执行结果如下:

[1] 2202

ext4

ext3

ext2

# 按下回车

[1]+ 完成 cat /etc/filesystems | grep --

color=auto ext

第一行表示作业和进程 ID,可以看到作业号是 1,进程 ID 是2022

第 3-4 行表示该程序运行的结果,过滤 /etc/filesystems 有关 ext 的内容

第 6 行分别表示作业号、默认作业、作业状态以及所执行的命令

关于默认作业:对于一个用户来说,只能有一个默认作业(+),同时也只能有一个即将成为默认作业的作业(-),当默认作业退出后,该作业会成为默认作业。

+:表示该作业号是默认作业

-:表示该作业即将成为默认作业

无符号:表示其他作业

作业状态 

常见的作业状态如下表所示:

作业的挂起与切回 

作业挂起 

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

例如我们运行一个死循环的程序、通过 ctrl + Z 将该作业挂起,观察一个对应的作业状态:

#include <stdio.h>

int main()
{
    while(1)
    {
        printf("hello\n");
    }
    return 0;
}

可以发现通过 ctrl + z 将作业挂起,该作业状态已经变为了停止状态 

作业切回 

如果想将挂起的作业切回,可以通过 fg 命令,fg 后面可以跟作业号或作业的命令名称。如果参数缺省则会默认将作业号为 1 的作业切到前台来执行,若当前系统只有一个作业在后台进行,则可以直接使用 fg 命令不带参数直接切回。具体的参数参考如下:

参数含义
%nn为正整数,表示作业号
%string以字符串开头的命令所对应的作业
%?string包含字符串的命令所对应的作业
%+或%%最近提交的一个作业
%-倒数第二个提交的作业

例如我们把刚刚挂起来的 ./test 作业切回到前台:

运行结果为开始无限循环打印 hello,可以发现该作业已经切换到前台了。

注意:当通过 fg 命令切回作业时,若没有指定作业参数,此时会将默认作业切到前台执行,即带有 “*” 的作业号的作业 

查看后台执行或挂起的作业 

我们可以直接通过输入 jobs 命令查看本用户当前后台执行或挂起的作业

参数 -1 则显示作业的详细信息

参数 -p 则只显示作业的 PID 

例如,我们先在后台及前台运行两个作业,并将前台作业挂起,来用 jobs 命令查看作业相关的信息:

作业控制相关的信号 

上面我们提到了键入 ctrl + z 可以将前台作业挂起,实际上是将 STGTSTP 信号发送至前台进程组作业中的所有进程,后台进程组中的作业不受影响。在 unix 系统中,存在 3 个特殊字符可以使得终端驱动程序产生信号,并将信号发送至前台进程组作业,它们分别是 :

crtl + C :中断字符,会产生 SIGINT 信号

ctrl + \ :退出字符,会产生 SIGQUIT 信号

ctrl + z :挂起字符,会产生 STGSTP 信号 

终端的 I/O (即标准输入和标准输出)和终端产生的信号总是从前台进程组作业连接打破实际终端。

5. 守护进程

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

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

void Daemon(bool ischdir,bool isclose)
{
    //1. 忽略可能引起程序员异常退出的信号
    signal(SIGCHLD,SIG_IGN);
    signal(SIGPIPE,SIG_IGN);
    //2. 让自己不要成为组长
    if(fork > 0)
        exit(0);
    //3. 设置让自己成为一个新的会话,后面的代码其实是子进程在走
    setsid();
    //4. 每一个进程都有自己的 CWD,是否将当前进程的 CWD 更改成为 /根目录
    if(ischdir)
        chdir(root);
    //5. 已经变成守护进程啦,不需要和用户的输入输出,错误进行关联
    if(isclose)
    {
        close(0);
        close(1);
        close(2);
    }
    else 
    {
        // 这里一般建议就用这种
        int fd = open(dev_null,O_RDWR);
        if(fd > 0)
        {
            dup2(fd,0);
            dup2(fd,1);
            dup2(fd,2);
            close(fd);
        }
    }
}

这个 Daemon 函数的目的是将一个程序转化为守护进程。它完成了一下几个步骤:

1. 忽略一些信号,防止进程异常退出

2. 使用 fork 确保父进程退出,使子进程成为孤儿进程。

3. 使用 setsid 创建新的会话,并使进程不再与终端相关。

4. 可选地将当前工作目录更改为根目录 / ,避免占用启动目录。

5. 关闭或重定向标准输入输出,确保守护进程不再与终端交互

通过这些步骤,程序就能以守护进程的方式在后台运行,不再依赖用户终端或任何终端的交互。

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

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

相关文章

LightGBM分类算法在医疗数据挖掘中的深度探索与应用创新(上)

一、引言 1.1 医疗数据挖掘的重要性与挑战 在当今数字化医疗时代,医疗数据呈爆炸式增长,这些数据蕴含着丰富的信息,对医疗决策具有极为重要的意义。通过对医疗数据的深入挖掘,可以发现潜在的疾病模式、治疗效果关联以及患者的健康风险因素,从而为精准医疗、个性化治疗方…

【文档搜索引擎】缓冲区优化和索引模块小结

开机之后&#xff0c;首次制作索引会非常慢&#xff0c;但后面就会快了 重启机器&#xff0c;第一次制作又会非常慢 这是为什么呢&#xff1f; 在 parserContent 里面&#xff0c;我们进行了一个读文件的操作 计算机读取文件&#xff0c;是一个开销比较大的操作&#xff0c; …

html+css网页设计 旅游 移动端 雪花旅行社4个页面

htmlcss网页设计 旅游 移动端 雪花旅行社4个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 …

3 JDK 常见的包和BIO,NIO,AIO

JDK常见的包 java.lang:系统基础类 java.io:文件操作相关类&#xff0c;比如文件操作 java.nio:为了完善io包中的功能&#xff0c;提高io性能而写的一个新包 java.net:网络相关的包 java.util:java辅助类&#xff0c;特别是集合类 java.sql:数据库操作类 IO流 按照流的流向分…

从零创建一个 Django 项目

1. 准备环境 在开始之前&#xff0c;确保你的开发环境满足以下要求&#xff1a; 安装了 Python (推荐 3.8 或更高版本)。安装 pip 包管理工具。如果要使用 MySQL 或 PostgreSQL&#xff0c;确保对应的数据库已安装。 创建虚拟环境 在项目目录中创建并激活虚拟环境&#xff…

ubuntu20.04安装imwheel实现鼠标滚轮调速

ubuntu20.04安装imwheel实现鼠标滚轮调速 Ubuntu 系统自带的设置中仅具备调节鼠标速度的功能&#xff0c;而无调节鼠标滚轮速度的功能。其默认的鼠标滚轮速度较为缓慢&#xff0c;在查看文档时影响尚可接受&#xff0c;但在快速浏览网页时&#xff0c;滚轮速度过慢会给用户带来…

GitLab的安装与卸载

目录 GitLab安装 GitLab使用 使用前可选操作 修改web端口 修改Prometheus端口 使用方法 GitLab的卸载 环境说明 系统版本 CentOS 7.2 x86_64 软件版本 gitlab-ce-10.8.4 GitLab安装 Gitlab的rpm包集成了它需要的软件&#xff0c;简化了安装步骤&#xff0c;所以直接…

简单工厂模式和策略模式的异同

文章目录 简单工厂模式和策略模式的异同相同点&#xff1a;不同点&#xff1a;目的&#xff1a;结构&#xff1a; C 代码示例简单工厂模式示例&#xff08;以创建图形对象为例&#xff09;策略模式示例&#xff08;以计算价格折扣策略为例&#xff09;UML区别 简单工厂模式和策…

脑肿瘤检测数据集,对9900张原始图片进行YOLO,COCO,VOC格式的标注

脑肿瘤检测数据集&#xff0c;对9900张原始图片进行YOLO&#xff0c;COCO&#xff0c;VOC格式的标注 数据集分割 训练组 70&#xff05; 6930图片 有效集 20&#xff05; 1980图片 测试集 10&#xff05; 990图片 预处理 静态裁剪&#xff1a; 24-82&…

YOLOv8 | 训练自定义数据集

目录 1 处理数据集1.1 数据集格式介绍1.2 划分数据集1.3 在 YOLOv8 中配置数据集 2 训练 YOLOv8 模型2.1 模型训练代码2.2 开启 TensorBoard 若尚未部署 YOLOv8&#xff0c;则可参考这篇博客&#xff1a; YOLOv8 | Windows 系统下从零开始搭建 YOLOv8 项目环境 1 处理…

Java设计模式 —— 【结构型模式】外观模式详解

文章目录 概述结构案例实现优缺点 概述 外观模式又名门面模式&#xff0c;是一种通过为多个复杂的子系统提供一个一致的接口&#xff0c;而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口&#xff0c;外部应用程序不用关心内部子系统的具体的细节&#xff0c;这…

可编辑99PPT | 智能工厂整体规划方案及实施细部方案

荐言分享&#xff1a;智能工厂是利用物联网、大数据、人工智能等先进技术&#xff0c;实现生产过程自动化、智能化和柔性化的现代工厂。本整体规划方案旨在通过整合信息技术、自动化技术、人工智能技术和物联网技术&#xff0c;构建一个高效、灵活、绿色、可持续的生产环境&…

Allegro17.4创建异形焊盘速通

Allegro17.4创建异形焊盘速通 打开Padstack Editor 17.4&#xff0c;新建焊盘&#xff0c;以标贴焊盘为例: 该标贴焊盘是在底面&#xff0c;选择END LAYRE &#xff0c;选择 Shape symbol Geometry&#xff0c;Shape symbol选择框右边有选择键&#xff0c;跳到Library Shape S…

多行为级联24|多行为推荐的超图增强级联图卷积网络

挂到arxiv上的&#xff0c;多行为级联超图加对比学习,超图是针对单个行为的&#xff0c;而不是针对多个行为的。参考的类似工作是CRGCN加MBSSL。这两篇我都做了论文阅读&#xff0c;&#xff08;CRGCN正在路上&#xff0c;MBSSL是我的第一篇论文阅读帖子&#xff09;推荐系统论…

利用.NET Upgrade Assitant对项目进行升级

本教程演示如何把WPF程序从 <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>升级到<TargetFramework>net8.0-windows</TargetFramework>. 下载并安装.NET Upgrade Assistant - Visual Studio Marketplace Supported .NET upgrades: .NET Frame…

Vue2四、 scoped样式冲突,data是一个函数,组件通信-父传子-子传父-非父子

组件通信 1. 父组件通过 props 将数据传递给子组件 2. 子组件利用 $emit 通知父组件修改更新 父--->子 子--->父

第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ

Q1、统计符合条件长度为3的子数组数目 1、题目描述 给你一个整数数组 nums &#xff0c;请你返回长度为 3 的子数组&#xff0c;满足第一个数和第三个数的和恰好为第二个数的一半。 子数组 指的是一个数组中连续 非空 的元素序列。 2、解题思路 我们需要在给定的数组 nums…

PSDK的编译与ROS包封装

本文档讲述在NIVIDIA开发板上使用大疆提供的Payload SDK获取无人机实时GPS信息的方法&#xff0c;以及基于Payload SDK发布ROS GPS话题信息的方法。 文章目录 0 实现目标1 Payload SDK1.1 PSDK 源码的编译1.2 PSDK 的使用 2 遥测数据的读取2.1 示例代码结构2.2 读取机载GPS信息…

铝电解电容使用寿命

铝电解电容寿命问题 铝电解电容为什么会失效&#xff1f;铝电解电容失效与那些因素有关&#xff1f;电解电容寿命如何计算&#xff1f; 1铝电解电容为什么会失效&#xff1f; 电容都是由两个导电板并排放到一起就构成了。正极是铝&#xff08;阳极箔&#xff09;&#xff0c;…

用Python PySide6 复刻了两软件UI 做下练习

图样 1 代码 1&#xff1a; # -*- coding: utf-8 -*-import sys from PySide6.QtCore import (QCoreApplication, QMetaObject, QRect, QDate) from PySide6.QtGui import QIcon, QPixmap, QColor from PySide6.QtWidgets import (QApplication, QDialog, QLineEdit, QPushBut…