进程关系与守护进程

进程关系与守护进程

  • 1. 进程组
  • 2. 会话
  • 3. 控制终端
  • 4. 作业控制
  • 5. 守护进程

1. 进程组

  1. 什么是进程组

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

C++
$ ps -eo pid,pgid,ppid,comm | grep test
#结果如下
PID PGID PPID COMMAND
2830 2830 2259 test
# -e 选项表示 every 的意思, 表示输出每一个进程信息
# -o 选项以逗号操作符(,)作为定界符, 可以指定要输出的列
  1. 组长进程

每一个进程组都有一个组长进程。 组长进程的 ID 等于其进程 ID, 如果只有一个进程那么他自己就是组长。我们可以通过 ps 命令看到组长进程的现象:

我们执行这条指令:sleep 1000 | sleep 2000 | sleep 300
会得到三个进程
在这里插入图片描述
所以第一创建出来的就是进程组长

  • 进程组组长的作用: 进程组组长可以创建一个进程组或者创建该组中的进程
  • 进程组的生命周期: 从进程组创建开始到其中最后一个进程离开为止。注意:主要某个进程组中有一个进程存在, 则该进程组就存在, 这与其组长进程是否已经终止无关
int main()
{pid_t pid = fork();if (pid == 0){while (1){std::cout << "I am child process pid:" << getpid() << std::endl;}}std::cout << "I am father process pid:" << getpid() << std::endl;sleep(5);exit(0);return 0;
}

在这里插入图片描述

2. 会话

  1. 什么是会话

在这里插入图片描述
在这里插入图片描述
当我在连接一个终端的时候,就会新增加一个会话。
在这里插入图片描述

会话其实和进程组息息相关,会话可以看成是一个或多个进程组的集合, 一个会话可以包含多个进程组。每一个会话也有一个会话 ID(SID)。
在这里插入图片描述

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

Shell
[node@localhost code]$ proc2 | proc3 &
[node@localhost code]$ proc4 | proc5 | proc6 &

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

Shell
#用管道和 sleep 组成一个进程组放在后台运行
[node@localhost code]$ sleep 1000 | sleep 2000 | sleep 3000 &
并将刚才我们写的代买执行起来
[node@localhost code]$ ./a.out
#查看 ps 命令打出来的列描述信息
[node@localhost code]$ ps axj | head -1 && ps axj | grep -E ‘sleep|a.out’
#&表示将进程组放在后台执行
#-E 选项:支持一点选项的通配
在这里插入图片描述
在这里插入图片描述

  1. 创建会话

  2. 会话id

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

3. 控制终端

先说一下什么是控制终端?
在 UNIX 系统中,用户通过终端登录系统后得到一个 Shell 进程,这个终端成为 Shell进程的控制终端。控制终端是保存在 PCB 中的信息,我们知道 fork 进程会复制 PCB中的信息,因此由 Shell 进程启动的其它进程的控制终端也是这个终端。默认情况下没有重定向,每个进程的标准输入、标准输出和标准错误都指向控制终端,进程从标准输入读也就是读用户的键盘输入,进程往标准输出或标准错误输出写也就是输出到显示器上。另外会话、进程组以及控制终端还有一些其他的关系,我们在下边详细介绍一下:
○ 一个会话可以有一个控制终端,通常会话首进程打开一个终端(终端设备或伪终端设备)后,该终端就成为该会话的控制终端。
○ 建立与控制终端连接的会话首进程被称为控制进程。
○ 一个会话中的几个进程组可被分成一个前台进程组以及一个或者多个后台进程组。
○ 如果一个会话有一个控制终端,则它有一个前台进程组,会话中的其他进程组则为后台进程组。
○ 无论何时进入终端的中断键(ctrl+c)或退出键(ctrl+\),就会将中断信号发送给前台进程组的所有进程。
○ 如果终端接口检测到调制解调器(或网络)已经断开,则将挂断信号发送给控制进程(会话首进程)。
这些特性的关系如下图所示:
在这里插入图片描述

4. 作业控制

  1. 什么是作业(job)和作业控制

1.作业是针对用户来讲,用户完成某项任务而启动的进程,一个作业既可以只包含一个进程,也可以包含多个进程,进程之间互相协作完成任务, 通常是一个进程管道。
2.Shell 分前后台来控制的不是进程而是作业 或者进程组。一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成,Shell 可以同时运⾏一个前台作业和任意多个后台作业,这称为作业控制。

在这里插入图片描述

  1. 作业号

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

可以通过命令:jobs -l查看详细信息
在这里插入图片描述
对于一个用户来说,只能有一个默认作业(+),同时也只能有一个即将成为默认作业的作业(-),当默认作业退出后,该作业会成为默认作业。
+: 表示该作业号是默认作业
-:表示该作业即将成为默认作业
无符号: 表示其他作业

  1. 作业状态

在这里插入图片描述

  1. 作业的挂起和切回
  • fg [作业号]切换到前台工作
    ctrl + z 终端运行
    在这里插入图片描述
  • 可以通过命令:bg [作业号] 唤醒作业
    在这里插入图片描述
  1. 作业控制相关的信号

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

  • Ctrl + C: 中断字符, 会产生 SIGINT 信号
  • Ctrl + \: 退出字符, 会产生 SIGQUIT 信号
  • Ctrl + Z:挂起字符, 会产生 STGTSTP 信号

终端的 I/O(即标准输入和标准输出)和终端产生的信号总是从前台进程组作业连接打破实际终端。我们可以通过下体来看到作业控制的功能:
在这里插入图片描述

5. 守护进程

  1. 什么是守护进程

这里我们要明白的是,一个进程或者是进程组,无论是前台或者后台都是属于同样个会话的。也就是说一旦我们的会话出现问题了,会话里的进程/进程组都会收到影响。但是向我们日常生活当中的服务器我们是不希望出现这种状况的,因为我们在一个会话中肯定不止会出现一个进程,而且我们也不能保证我们创建的这个会话会一直存在,一直不会出现问题,而服务器确实启动在我们创建的会话里的。所以为了不让服务器收到影响,我们需要将服务器单独的放到一个会话中,形成一个独立的会话,所以这个时候,服务器就由原来的与我们一开始创建的会话成包含关系,变成了并列关系,所以就算我一开始创建的会话出问题了甚至是删除了也不会影响到服务器。所以像这样一个会话中只包含一个进程/进程组我们称之为守护进程
所以一旦服务器称为了守护进程,服务器就不会受到用户的登陆和注册的影响。

  1. 如何将服务守护进程化

调用函数
C
#include <unistd.h>
/*
*功能:创建会话
*返回值:创建成功返回 SID, 失败返回-1
*/
pid_t setsid(void);
该接口调用之后会发生:

  • 调用进程会变成新会话的会话首进程。 此时, 新会话中只有唯一的一个进程
  • 调用进程会变成进程组组长。 新进程组 ID 就是当前调用进程 ID
  • 该进程没有控制终端。 如果在调用 setsid 之前该进程存在控制终端, 则调用之后会切断联系
  • 需要注意的是: 这个接口如果调用进程原来是进程组组长, 则会报错, 为了避免这种情况, 我们通常的使用方法是先调用 fork 创建子进程, 父进程终止, 子进程继续执行,而就算父进程结束了,子进程的组长依旧是父进程, 因为子进程会继承父进程的进程组 ID, 而进程 ID 则是新分配的, 就不会出现错误情况,这个时候子进程就变成了孤儿进程,所以守护进程是孤儿进程的一种特殊进程。

在介绍一个函数daemon
这里daemon函数是有setsid封装而来的:
在这里插入图片描述
daemon()函数适用于希望从控制终端脱离并作为系统守护进程在后台运行的程序。

  • 如果nochdir为零,daemon()将进程的当前工作目录更改为根目录(“/”); 否则,当前工作目录保持不变。
  • 如果noclose为零,daemon()将标准输入,标准输出和标准错误重定向到/dev/null; 否则,不会对这些文件描述符进行更改。(参数为0时有效)

封装实现

#include <iostream>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>const static std::string defaultworkdir = "/";
const static std::string defaultdev = "/dev/null";void Daemon(int ischdir, int isclose)
{// 1. 忽略不必要的型号signal(SIGCHLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);// 2. fork 让子进程进行创建if (fork() > 0)exit(0);// 3. setsid()setsid();// 4. 确定是否更改工作目录if (!ischdir)chdir(defaultworkdir.c_str());// 5. 对标准文件012进行重定性if (!isclose){::close(0);::close(1);::close(2);}else{int fd = open(defaultdev.c_str(), O_RDWR);if (fd > 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);::close(fd);}}
}
int main()
{Daemon(1,1);while (1){sleep(1);}return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

猫头虎分享:PyTorch异常ModuleNotFoundError: No module named ‘torch’解决方案

&#x1f42f; 猫头虎分享&#xff1a;PyTorch异常ModuleNotFoundError: No module named ‘torch’解决方案 &#x1f4bb; 摘要 在本篇博客中&#xff0c;我们将深入探讨如何解决PyTorch中常见的“ModuleNotFoundError: No module named ‘torch’”错误。通过详细的步骤指…

如何在 VitePress 中自定义logo,打造精美首页 #home-hero-image

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

【matlab】使用movefile批量修改命名,并保留原命名中指定的数字

【matlab】使用movefile批量修改命名&#xff0c;并保留原命名中指定的数字 文章目录 【matlab】使用movefile批量修改命名&#xff0c;并保留原命名中指定的数字一、情况说明二、代码示例通配符正则表达式匹配 (regexp 函数):提取捕获组中的数字 (number 变量): 一、情况说明 …

CTF之网站被黑

简单看一下网页和源码没发现什么明显漏洞 那就扫描一下目录 发现了/shell.php文件&#xff0c;访问一下&#xff0c;发现是一个后台管理登录页面 别无他法只能爆破喽&#xff0c;爆破后发现密码是hack flag{25891d9e9d377f006eda3ca7d4c34c4d}

rust学习——move关键字

示例讲解 在闭包章节中&#xff0c;有讲过 move 关键字在闭包中的使用可以让该闭包拿走环境中某个值的所有权&#xff0c;同样地&#xff0c;你可以使用 move 来将所有权从一个线程转移到另外一个线程。 首先&#xff0c;来看看在一个线程中直接使用另一个线程中的数据会如何…

22.备份交换机-处理无法投递的消息

前面提到当消息发送给交换机&#xff0c;交换机出故障&#xff0c;或者队列出现故障&#xff0c;会反馈给生产者。 如果交换机备份&#xff0c;将无法投递的消息发送给备份交换机&#xff0c;再由备份交换机给备份队列和告警队列的思路&#xff0c;来防止消息不丢失。 小提示…

探索LLM世界:新手小白的学习路线图

随着人工智能的发展&#xff0c;语言模型&#xff08;Language Models, LLM&#xff09;在自然语言处理&#xff08;NLP&#xff09;领域的应用越来越广泛。对于新手小白来说&#xff0c;学习LLM不仅能提升技术水平&#xff0c;还能为职业发展带来巨大的机遇。那么&#xff0c;…

BGP路由反射器

原理概述 缺省情况下&#xff0c;路由器从它的一个 IBGP对等体那里接收到的路由条目不会被该路由器再传递给其他IBGP对等体&#xff0c;这个原则称为BGP水平分割原则&#xff0c;该原则的根本作用是防止 AS内部的BGP路由环路。因此&#xff0c;在AS内部&#xff0c;一般需要每台…

SAP PP学习笔记31 - 计划运行的步骤2 - Scheduling(日程计算),BOM Explosion(BOM展开)

上一章讲了计划运行的5大步骤中的前两步&#xff0c;计算净需求和计算批量大小。 SAP PP学习笔记30 - 计划运行的步骤1 - Net requirements calculation 计算净需求(主要讲了安全库存要素)&#xff0c;Lot-size calculation 计算批量大小-CSDN博客 本章继续讲计划运行的后面几…

Golang | Leetcode Golang题解之第283题移动零

题目&#xff1a; 题解&#xff1a; func moveZeroes(nums []int) {left, right, n : 0, 0, len(nums)for right < n {if nums[right] ! 0 {nums[left], nums[right] nums[right], nums[left]left}right} }

vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储

vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储&#xff01;实际业务开发中&#xff0c;token是一个表示着用户登录状态的重要信息&#xff0c;它有自己的生命周期。因此&#xff0c;这个参数值必须实例化存储在本地中。不能跟着pinia。因为pinia是基于内存设计的模…

使用法国云手机进行面向法国的社媒营销

在当今数字化和全球化的时代&#xff0c;社交媒体已经成为企业营销和拓展市场的重要工具。对于想进入法国市场的企业来说&#xff0c;如何在海外社媒营销中脱颖而出、抓住更多的市场份额&#xff0c;成为了一个关键问题。法国云手机正为企业提供全新的营销工具&#xff0c;助力…

photoshop学习笔记——移动工具

移动工具&#xff0c;可以对图层进行移动&#xff0c;快捷键 V 使用的素材已经放上了&#xff0c;直接下载即可 按住ctrl 可以自动选取&#xff0c;鼠标点击哪个对象&#xff0c;自动选中哪个图层 按住 shift 校正角度&#xff08;只能沿着直线移动&#xff09; 按住 alt 拖…

Redis的分布式锁

目录 一、定义与原理 基于Redis的分布式锁 获取锁 释放锁 锁误删问题&#xff1a;因为key值一样,将别人的锁删掉了 锁误判问题二&#xff1a;判断锁和释放锁不是原子性的 Lua脚本 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁 分布式锁的优点…

Linux驱动开发——字符设备驱动开发

1 概述 1.1 说明 本文是学习rk3568开发板驱动开发的记录&#xff0c;代码依托于rk3568开发板 1.2 字符设备介绍 字符设备是 Linux 驱动中最基本的一类设备驱动&#xff0c;字符设备就是一个一个字节&#xff0c;按照字节流进行读写操作的设备&#xff0c;读写数据是分先后顺…

Navicat Charts Creator for Mac:数据可视化利器

Navicat Charts Creator for Mac是一款专为Mac用户设计的数据可视化工具&#xff0c;它将复杂的数据转化为直观、易懂的图表&#xff0c;帮助用户更好地理解和分析数据。 该软件支持连接到多种数据库&#xff0c;如MySQL、MariaDB、PostgreSQL等&#xff0c;轻松获取实时数据&…

23 PCBEditor封装创建向导介绍24 PCBEditor3D封装展示25 PCB封装库的管理与调用

23 PCBEditor封装创建向导介绍_BGA为例&&24 PCBEditor3D封装展示&&25 PCB封装库的管理与调用 第一部分 23 PCBEditor封装创建向导介绍_BGA为例一、创建焊盘二、PCBEditor创建封装 第二部分 24 PCBEditor3D封装展示第三部分 25 PCB封装库的管理与调用一、指定库…

黑马头条vue2.0项目实战(二)——登录注册功能的实现

1. 布局结构 目标 能实现登录页面的布局 能实现基本登录功能 能掌握 Vant 中 Toast 提示组件的使用 能理解 API 请求模块的封装 能理解发送验证码的实现思路 能理解 Vant Form 实现表单验证的使用 这里主要使用到三个 Vant 组件&#xff1a; NavBar 导航栏 Form 表单 F…

Linux文件恢复

很麻烦 一般还是小心最好 特别恢复的时候 可能不能选择某个文件夹去扫描恢复 所以 删除的时候 用rm -i代替rm 一定小心 以及 探索下linux的垃圾箱机制 注意 一定要恢复到不同文件夹 省的出问题 法1 系统自带工具 debugfs 但是好像不能重启&#xff1f; testdisk 1、安装 …