Linux-进程间关系与守护进程

news2024/11/15 12:12:21

一、进程组

1.1 什么是进程组

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

C++
$ ps 查看进程的信息

# -e 选项表示 every 的意思, 表示输出每一个进程信息
# -o 选项以逗号操作符(,)作为定界符, 可以指定要输出的列
# -a 选项表示不仅列当前⽤户的进程,也列出所有其他⽤户的进程
# -x 选项表示不仅列有控制终端的进程,也列出所有⽆控制终端的进程
# -j 选项表示列出与作业控制相关的信息
int main()
{
    while(true)
    {
        std::cout<<"I am a process pid:"<<getpid()<<std::endl;
        sleep(1);
    }
    return 0;
}

我们发现尽管时单进程,这个进程也拥有自己的进程组,而进程组id就是单进程的pid

int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        while (true)
        {
            std::cout << "I am child process pid:" << getpid() << std::endl;
            sleep(1);
        }
    }
    std::cout << "I am father process pid:" << getpid() << std::endl;
    sleep(100);
    return 0;
}

接下来我们又创建了一个子进程,我们发现父子进程都是属于一个进程组的,并且进程组id是父进程的pid,因为父进程是这个进程组的第一个进程。在我们写的多进程程序中,都是以进程组的方式来执行任务的

1.2 组长进程

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

Shell
[node@localhost code]$ ps -o pid,pgid,ppid,comm | cat
# 输出结果
PID PGID PPID COMMAND
2806 2806 2805 bash
2880 2880 2806 ps
2881 2880 2806 cat
  • 进程组组长的作用: 进程组组长可以创建一个进程组或者创建该组中的进程
  • 进程组的生命周期: 从进程组创建开始到其中最后一个进程离开为止。

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

二、会话

2.1 什么是会话

会话其实和进程组息息相关, 会话可以看成是一个或多个进程组的集合, 一个会话可以包含多个进程组。每一个会 话也有一个会话 ID(SID),会话ID一般为会话中第一个进程组的第一个进程的id,

注意:会话 ID 在有些地方也被称为 会话首进程的进程组 ID, 因为会话首 进程总是一个进程组的组长进程, 所以两者是等价的

以我们登录Linux服务器为例,服务器内部一定是安装了系统的,当我们输入账号密码要登录的时候,系统首先会创建一个终端文件和一个与之关联的bash进程,而这个bash进程也是一个进程组,在Linux中终端文件一般保存在在 /dev/pts 目录下,我们可以将终端文件理解为我们输入命令的窗口(当前我一共打开了两个窗口),每打开一个窗口就会新创建一个文件

我们也可以查看一下系统中的bash进程,发现这两个bash进程属于不同的进程组和会话

2.2 如何创建会话

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

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

该接口调用之后会发生:

  • 调用进程会变成新会话的会话首进程。 此时, 新会话中只有唯一的一个进程
  • 调用进程会变成进程组组长。 新进程组 ID 就是当前调用进程 ID
  • 该进程没有控制终端。 如果在调用 setsid 之前该进程存在控制终端, 则调用之后会切断联系,因为处于不同的会话了

需要注意的是:

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

三、控制终端

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

  • 一个会话可以有一个控制终端,通常会话首进程打开一个终端(终端设备或 伪终端设备)后,该终端就成为该会话的控制终端。
  • 建立与控制终端连接的会话首进程被称为控制进程。
  • 一个会话只能有一个前台进程组,但是可以有多个后台进程组
  • 无论何时进入终端的中断键(ctrl+c)或退出键(ctrl+\),就会将中断信号 发送给前台进程组的所有进程。
  • 前后台进程的显著区别是是否占用终端(或控制台)的输入输出资源。

证明:

        默认情况下bash进程一般为前台进程组,假如我们执行了一个死循环打印的程序,这死循环中我们在终端中输入命令会发现bash进程并不会做出响应,这是因为当我们执行打印程序时,系统将我们的进程组设置为了前台进程组,bash进程暂时被设置为了后台进程组,而我们在终端输入的数据是给前台进程的所以bash就收不到我们的指令了,而当我们的程序终止时,bash进程会切换为前台进程,此时我们又可以正常执行指令了

 四、作业控制

4-1 什么是作业(job)和作业控制(Job Control)?

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

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

4.2 作业号

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

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

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

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

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

  • + : 表示该作业号是默认作业
  • -:表示该作业即将成为默认作业
  • 无符号: 表示其他作业
4.3 作业控制

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

作业挂起

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

作业切回

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

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

五、守护进程

5.1 什么是守护进程

守护进程(Daemon Process)是在Unix和类Unix操作系统(如Linux)中运行的一种特殊类型的进程。它们通常在系统启动时自动启动,并在后台运行,执行一些诸如监控或管理其他进程、系统服务、网络服务等任务。

守护进程的主要特点包括:

  1. 后台运行:守护进程在后台运行,不占用终端。这意味着用户不能直接与守护进程交互,除非通过某种形式的进程间通信(IPC)机制,如管道、信号、消息队列等。

  2. 独立于终端:守护进程一旦启动,就与启动它的终端或会话无关。即使终端关闭或会话结束,守护进程也会继续运行。

  3. 生命周期:守护进程通常设计为在系统运行期间持续运行,除非遇到错误、系统重启或管理员明确停止。

  4. 日志记录:守护进程通常会记录其运行状态、错误和警告到系统日志中,以便于管理员监控和故障排查。

  5. 低优先级:守护进程通常具有较低的进程优先级,以避免它们占用过多系统资源,影响其他关键任务。

  6. 无控制终端:守护进程没有控制终端。这意味着它们不能直接从终端接收输入或输出到终端。

5.2 守护进程实现
  • 创建子进程:父进程退出,子进程继续运行,避免该进程是一个进程组的组长,所以守护进程也是一种特殊的孤儿进程
  • 创建新会话:子进程调用 setid() 创建新的会话,成为会话领头进程,脱离原来的控制终端。
  • 改变工作目录:守护进程通常会改变其工作目录到根目录(/),以避免因非根目录不可访问而退出。
  • 设置文件权限掩码:守护进程通常会调用umask设置合适的文件权限掩码,以避免创建的文件具有不恰当的权限。
  • 关闭文件描述符:关闭文件描述符如标准输入、标准输出、标准错误,或者将他们重定向到    /dev/null 文件中,因为进程已经是守护进程了,不需要与用户关联了
  • /dev/null文件是一个特殊的字符类文件,当从这个文件中读取数据时什么也读不到,而当向这个文件写数据时,系统会默认丢弃

这里我们的参数ischdir和isclose是为了将是否改变进程的工作目录和关闭文件描述符暴露出来,供用户自己选择

#pragma once
#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);
        }
    }
}
5.3 如何将服务守护进程化
// ./server port
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cout << "Usage : " << argv[0] << " port" << std::endl;
        return 0;
    }
    uint16_t localport = std::stoi(argv[1]);
    Daemon(false, false);
    std::unique_ptr<TcpServer> svr(new TcpServer(localport,
                                                 HandlerRequest));
    svr->Loop();
    return 0;
}

此时服务端已经在后台开始运行,我们发现客户端可以正常进行业务处理

当我们关闭服务端会话,服务端依旧在后端正常执行,客户端依旧可以正常执行

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

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

相关文章

阻抗控制中的dynamic movement primitives(DMP) model

在阻抗控制中&#xff0c;Dynamic Movement Primitives (DMP) 模型被用于实现一种高度灵活且可泛化的轨迹模仿学习方法。DMP模型由美国南加州大学&#xff08;University of Southern California&#xff09;的Stefan Schaal教授团队于2002年提出&#xff0c;它通过将动态系统建…

Linux命令之二

Linux命令之二 VI和VIM编辑器1、VIM的一般模式①、删除复制操作②、光标移动操作 2、VIM的编辑模式3、VIM的命令模式4、三种模式之间的切换关系 权限管理文件类型和权限的表示文件属性介绍chmod 改变文件权限chown 改变所有者 yum 安装软件命令 Linux命令速查平台 VI和VIM编辑器…

IOy系列BL196MQTT远程IO模块推动智能交通信号控制

在当今这个快速发展的时代&#xff0c;城市化进程加速推进&#xff0c;随之而来的是日益严重的交通拥堵问题。为了缓解这一状况&#xff0c;智能交通信号控制系统应运而生&#xff0c;成为解决城市交通问题的有效手段之一。 一、钡铼技术BL196模块简介 钡铼技术推出的IOy系列…

【SQL】商品销售

目录 题目 分析 代码 题目 表&#xff1a; Product ----------------------- | Column Name | Type | ----------------------- | product_id | int | | product_name | varchar | | unit_price | int | ----------------------- product_id 是该表的主键…

Redis与CAP定理—理解数据存储的权衡

一、概述 在分布式系统的设计中&#xff0c;理解CAP定理的重要性是不言而喻的。CAP定理指出&#xff0c;一个分布式系统不可能同时完全满足一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;和分区容忍性&#xff08;Partition Toleran…

OCR识别行驶证(阿里云和百度云)

OCR识别行驶证(阿里云和百度云) 一、使用场景 1、通过识别行驶证&#xff0c;获取相关汽车信息&#xff0c;替代手输 二、效果图 三、代码部分&#xff1a; 1、阿里云OCR 1.1、控制层 PostMapping("/ocrCard") public JSONObject ocrCard(RequestPart("fi…

开放式耳机哪种好用?开放式种草测评!

现在很多人都很喜欢用开放式耳机了&#xff0c;因为这种耳机非常的舒服&#xff0c;而且不会压迫我们的耳道&#xff0c;从而给到我们更健康的体验&#xff0c;但是现在开放式耳机的品牌越来越多&#xff0c;我们也越来越难选择&#xff0c;所以我们应该怎么样才能选到一款适合…

ado.net 操作sqlite

新建控制台项目 安装nuget包Microsoft.Data.Sqlite 数据库名字和链接 string dbName "test.db"; SqliteConnection? connection null; try {//创建链接connection new SqliteConnection($"Data Source{dbName}");//打开链接connection.Open(); } ca…

RK33568 android12 背景图片替换

文章目录 前言一、直接文件替换二、使用属性替换1.属性获取图片的代码分析2.设置图片路径前言 项目中,需要替换背景图片,要求是黑色的背景图片 修改前: 修改后: 一、直接文件替换 文件路径 device/rockchip/rk356x/overlay/frameworks/base/core/res/res/drawable-nod…

为什么要用数字化营销管理平台?

数字化营销管理平台是一种利用数字技术来整合和优化营销流程的工具。它能够帮助企业更高效地进行市场推广、客户关系管理以及销售活动。 一、主要功能 1.数据整合与分析 整合多渠道数据&#xff0c;包括网站流量、社交媒体互动、电子邮件营销反馈等。通过数据分析&#xff0…

Docker 存储空间不足无法导入加载镜像

问题:在载入镜像时,发现docker没有空间了 解决办法: 更改docker的存储路径 1.添加新的硬盘 docker info #查看docker的存储位置 df -Th #查看占用以及挂载情况 发现没有可用的剩余空间,我们可以添加一个新的硬盘 在l

EMC学习之接地与平面

1 不同信号地的放置 下图为数字地和射频地的两种放置方式&#xff0c;第一个布局方式射频电流必须要经过数字地才能返回电源GND上&#xff0c;而且射频地与数字地之间的间隙很小&#xff0c;所以更容易通过寄生电容来耦合噪声。第二个布局数字地与射频地没有重叠&#xff0c;平…

iOS 18 Beta 5:苹果的细腻之笔,绘制用户体验新画卷

在苹果的世界里&#xff0c;每一次系统更新都是对用户体验进行的一次精心雕琢。 随着iOS 18 Beta 5的上线&#xff0c;苹果带来了一系列令人耳目一新的功能&#xff0c;同时也在系统的每个细微之处展现了对完美的追求。 Safari浏览器的“干扰控制”功能 在今天信息充斥的数字…

BF算法,KMP算法

前言&#xff1a;今天我们来学习两种算法&#xff0c;BF算法和KMP算法。相信会让许多小伙伴们打开新世界的大门。 1 BF算法 实践是检验真理的唯一标准。举一个例子说明BF算法。现在我们要在一个主串中找子串的位置。那我们该如何解决这个问题呢&#xff1f;最简单的办法自然是…

【数据结构-哈希前缀】力扣2845. 统计趣味子数组的数目

给你一个下标从 0 开始的整数数组 nums &#xff0c;以及整数 modulo 和整数 k 。 请你找出并统计数组中 趣味子数组 的数目。 如果 子数组 nums[l…r] 满足下述条件&#xff0c;则称其为 趣味子数组 &#xff1a; 在范围 [l, r] 内&#xff0c;设 cnt 为满足 nums[i] % mod…

springboot打包找不到主类

1.打包jar包 idea中点击项目结构project stucture ,选择artfacts 2.

机器学习辅助复合材料预测,性能管理优化创新材料,这种王炸般的组合,还真是大开眼界!

在人工智能与复合材料技术融合的背景下&#xff0c;复合材料的研究和应用正迅速发展&#xff0c;创新解决方案层出不穷。从复合材料性能的精确预测到复杂材料结构的智能设计&#xff0c;从数据驱动的材料结构优化到多尺度分析&#xff0c;人工智能技术正以其强大的数据处理能力…

网络空间安全考研方向:5大专业值得选择,你喜欢哪一个?

网络空间安全考研方向包括网络与信息安全、信息安全工程、信息对抗技术、信息安全与管理、网络安全与执法等专业&#xff0c;旨在培养网络安全领域的高级专业人才&#xff0c;涵盖网络攻击与防御、信息加密与解密、信息安全评估与管理等核心知识与技能&#xff0c;为国家和社会…

4、物品抓取(6自由度机械臂逆运动学)

目录 1.坐标系建立 2.运用解析法计算各个舵机旋转角度 ​3.举例 1.坐标系建立 采用笛卡尔坐标系图1&#xff0c;即由三个互相垂直的坐标轴所组成的坐标系&#xff0c;以机械臂正向为X轴方向&#xff0c;横向为Y轴方向&#xff0c;纵向为Z轴方向。 图1 笛卡尔坐标系 2.运用…

实现qt的多语言转换

前言&#xff1a;qt实现多语言转换主要&#xff0c;用到lrelease.exe&#xff0c;在QT下运行图片和语言转换&#xff0c;需要对对应格式的内容进行转换。图片和语言&#xff0c;甚至是字体均是通过添加.qrc配置&#xff0c;来转换。图片转换成.rcc格式。而语言通过在.excel编辑…