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

进程间关系与进程守护

一、进程组

1、理解

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

2、举例

上图就是用管道创建了一个进程组。

我们可以用 ps ajx | head -1 && ps ajx | grep sleep,来查看指定的进程。
发现PGID是一样的2114632。

3、结论

PGID是进程组组长的PID,进程组组长可以创建一个进程组,也可以在自己的进程组里面创建新进程(父进程)
进程组的声明周期终止于最后一个进程退出,与组长无关。

二、会话

1、理解

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

如三个进程SID相同,说明组成的进程组在同一个会话中。

2、Linux会话结构

首先我们登录Linux之后,先有 bash 进程创建终端文件,此时 bash 不仅是进程组组长,bash 进程组还是会话组长,我们大部分的工作都是在 bash 创建的会话里面完成的。建立与控制终端连接的会话首进程是控制进程 bash。

3、结论

(1)在同一个会话中允许存在多个进程组。

(2)但是前台进程只有一个,后台进程可以有多个

例如我在前台启动一个进程组,输入指令 bash 由于在后台,就不会处理指令。

(3)前后台:前台可以从标准输入中获取数据。进程在启动时最后带上&就是后台进程

(4)无论何时,发送的中断信号只能给前台进程。

三、控制终端

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

四、作业与作业控制

1、理解

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

2、作业控制操作

jobs:查看作业。-p查看作业pid

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

fg 作业号:把一个指定作业提到前台(接受用户输入的数据)

把作业放回后台:(1)作业暂停(ctrl z,也叫挂起)之后OS就会把作业放回后台。(2)bg 作业号:在后台启动作业

3、作业状态

4、举例

五、守护进程

1、理解

一个服务进程独立成为一个会话,就不会受原来会话的影响。

2、把进程变成守护进程

不是进程组组长调用函数 setsid 就可以把自己变成守护进程。调用的进程就会变成新会话的首进程,此时会话中只有一个进程,也是一个进程组的组长。

做法:父进程先 fork 子进程,父进程退出,子进程调用函数,由于子进程继承父进程的进程组id,进程id被重新分配,所以守护进程是孤儿进程。

这种进程已经不属于 bash 会话,只能用 kill 杀死进程。

3、代码实现

#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 = "/";
// 路径/dev/null 文件里面的数据不能被读取,相当于是被丢弃
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);}}
}

http://www.mrgr.cn/news/28812.html

相关文章:

  • ZooKeeper远程连接超时排查与解决
  • 如何用安卓玩Java版Minecraft,安卓手机安装我的世界Java版游戏的教程
  • 过拟合与欠拟合、批量标准化
  • docker- No space left on device
  • 开源模型应用落地-qwen模型小试-调用Qwen2-VL-7B-Instruct-更清晰地看世界(一)
  • 紧急预警!台风贝碧嘉正面袭击上海浦东,风雨交加影响全城
  • 自然语言处理实战项目
  • 文件标识符fd
  • 【看这里】记录一下,如何在springboot中使用EasyExcel并行导出多个Excel文件并压缩zip后下载
  • Java 性能调优:优化 GC 线程设置
  • 【C++前后缀分解】1653. 使字符串平衡的最少删除次数|1793
  • DFS:二叉树中的深搜
  • Qt_输入类控件
  • 破损shp文件修复
  • 代码随想录算法训练营第57天|卡码网 53. 寻宝 prim算法精讲和kruskal算法精讲
  • 中位数贪心+分组,CF 433C - Ryouko‘s Memory Note
  • C++基于select和epoll的TCP服务器
  • 问题——IMX6UL的uboot无法ping主机或Ubuntu
  • 基于形状记忆聚合物的折纸超结构
  • 速通LLaMA2:《Llama 2: Open Foundation and Fine-Tuned Chat Models》全文解读