任务管理与守护进程

news2024/12/23 3:26:40

1.前台进程与后台进程

1.1守护进程

在上一章中,我们实现了一个Tcp服务器,但是这个服务器还存在一些问题,例如,我们将云服务器(xshell)关闭之后,服务器就无法使用了。

但是真正的服务器肯定不是这样的,启动之后不受用户影响,除非主动将这个服务器kill掉。我们考虑将服务器修改成为守护进程

守护进程(Daemon)是在计算机操作系统中以后台形式运行的一类特殊进程。这些进程在系统启动时被启动,并持续在后台运行,直到系统关闭。它们不依赖于任何用户交互,也不与任何终端相关联。

1.2前台进程

前台进程就是那些我们能够直接看到并与之交互的进程。比如我们使用xshell,Linux服务器会为我们提供一个命令行解释器bash。这个命令行解释器就是一个前台进程,会与用户交互。

1.3后台进程

后台进程(Background Process)是指在计算机操作系统中运行但不在前台显示界面的进程。与前台进程不同,后台进程通常不会直接与用户交互,而是在系统后台默默地执行各种任务。

当我们调用一个sleep之后,就会卡住,原因就是操作系统会执行创建一个进程去执行sleep 1000。此时这个进程就自动变成了前台进程,而bash变成了后台进程,此时我们想执行shell命令也无法执行,因为此时与我们交互的进程是sleep 1的进程。

而我们刚刚说的守护进程其实就属于后台进程。

1.4前后台进程转换

在启动服务时,在后面加一个 符号就可以让该进程在后台运行

可以看到,sleep变成后台进程后,我们不会像上面一样卡住了。

我们可以使用jobs命令查看后台运行的任务

如果是已经运行的前台进程或者后台进程呢

后台进程转前台

使用 fg + 任务编号  就可以把一个后台任务放到前台

注意:前台进程只能有一个,当一个进程变成前台进程后,bash会自动变成后台进程,此时命令行就无法使用了。

前台进程转后台

使用 [Ctrl Z] + bg + 任务编号 就可以把前台进程放到后台

先使用 [Ctrl Z] 我们会发现,这个进程就会进入停止状态(Stopped), 再使用bg + 任务编号,就可以将这个进程在后台开始运行(Runing)

2.任务管理

2.1进程组

每个进程属于一个进程组,每个进程组中包含一个或多个进程。并且每个进程组都会有个进程组组长,通常是创建这个组的第一个进程的PID,也就是说进程组的组长的PID和组ID相等。

当我们使用ps命令就可以查看进程的组ID(PGID),上面的例子中,两个进程属于不同的进程组。

我们执行了sleep命令后,系统会帮我们创建进程去执行sleep,此时我们发现,使用管道连接的几个进程的组ID(PGID)是相同的。

2.2作业

作业是用户在一次解题或一个事务处理过程中要求计算机系统所做的工作的集合,包括用户程序、所需的数据和命令等。作业管理涉及从提交作业到得到运行结果并最终退出系统的整个管理过程。作业与进程组有一定的关联,因为进程组可以被视为作业的表示。

jobs就是用于查看linux中的作业列表,最左边的编号就是任务号。一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成,Shell可以运行一个前台作业和任意多个后台作业,这称为作业控制。

2.3会话

会话就是一个或者多个进程组的集合

在一个会话中,通常有一个特殊的进程被指定为会话首领(session leader),它是该会话的控制进程,通常是由用户启动的程序(如shell)。会话首领的进程ID就是该会话的ID。一个会话可以包含多个进程组,每个进程组有一个唯一的进程组ID。

任何时刻,一个会话中会有很多个进程组。但是任何时刻只允许一个在前台。

SID就是会话ID

2.4如何理解

我们先写两个命令,第一个是启动两个进程,并且放到后台运行,第二个是启动三个进程在前台运行

此时我们查看一下这几个进程

前面两个属于一个后台进程组,后面的三个属于一个前台进程组。但是这五个进程都属于一个会话

实际上我们每次登录的时候,都会为我们创建一个新会话,我们可以使用ps命令查看会话

我们登录四个用户,查看每个bash的会话ID发现都不一样

再举个例子,理解进程组,作业,会话三者之间的关系

进程组

进程组就像是一个团队,他们在一起做同样的事情。进程组可以帮助操作系统集中管理这些相关的进程,比如发送相同的信号给所有的进程。

会话

会话就像是一场厨艺比赛。在这个比赛上,可能有多个团队,他们都在同一个环境下(场地)进行各自的活动。会话首领就像是这个比赛的负责人,负责整个比赛的组织和协调。

作业

作业就像是比赛过程中的任务(比如做饭)。这个任务需要多个进程(切菜、炒菜、煮饭等)合作完成,这些进程组成了一个作业。作业管理就是确保这些进程能够按照正确的顺序和方式执行,最终完成整个任务。

3.守护进程

守护进程(Daemon)是在计算机操作系统中以后台形式运行的一类特殊进程,它们在系统启动时被启动,一直运行在后台,不依赖于任何用户交互,也不与任何终端相关联。主要用于执行特定的系统任务,如管理网络服务、定时任务、系统监控、日志记录等。

守护进程是一个独立的会话,不隶属于任何一个bash

左边就是我们之前的方式,右边是守护进程的方式。

3.1成为守护进程的条件

  • 守护进程必须是孤儿进程
  • 守护进程不能是进程组的组长
  • 忽略掉异常信号(可能会导致进程退出)
  • 守护进程要脱离终端(不能与显示器交互),所以我们要关闭 / 重定向0,1,2三个文件描述符

我们不建议之间将这几个文件描述符关闭,因为可能会有一些日志信息需要打印,但是0,1,2文件描述符已经关闭,所以会向不存在的文件中写入时就会出错。

系统为我们提供了一个/dev/null文件,/dev/null文件会帮我们清空写入的数据,就像是一个垃圾桶一样。所以我们可以将文件重定向到/dev/null中。

3.2成为守护进程的步骤

  1. 忽略信号:忽略可能会引起程序异常退出的信号,例如SIGCHLD,SIGPIPE等。
  2. 创建子进程:通过调用fork()创建新的子进程,然后让父进程立即退出。这样,子进程将成为一个孤儿进程,被init进程(PID为1的进程)接管,从而脱离控制终端。
  3. 创建新的会话:在子进程中调用setsid(),创建一个新的会话,并成为会话的首领。这样,守护进程将拥有一个独立的会话和进程组,不再与终端相关联。
  4. 改变工作目录:将当前工作目录改为根目录或其他合适的目录,以切断与原始文件系统的联系。
  5. 重定向标准I/O:将标准输入、标准输出和标准错误输出重定向到/dev/null,以确保守护进程不依赖于任何终端的I/O操作。
  6. 关闭不必要的文件描述符:关闭所有不必要的文件描述符,防止它们被继承并在后续操作中造成冲突。

我们先学习一下一个函数

#include <unistd.h>

pid_t setsid(void);

setsid系统函数用于启动一个进程,并将其与当前会话分离。调用setsid函数的进程会成为新的会话的领头进程,并与其父进程的会话组和进程组脱离。

调用setsid函数的进程需要满足一定条件,它不能是组长进程,并且需要有对应的创建session的权限。

在实际应用中,setsid系统函数常用于实现守护进程(daemon),即那些在系统启动时开始运行,并在后台持续运行以提供服务或执行任务的进程。通过将进程与会话分离,守护进程可以独立于控制终端运行,从而确保即使终端关闭,守护进程也能继续执行其任务。

3.3代码实现

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

const char* defaultPwd = "/";
const char* devnull = "/dev/null";

void Daemon(bool ifchdir, bool ifclose)
{
    //1.忽略异常信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    //2.创建子进程
    if (fork() > 0)
        exit(0);

    //3.创建新的会话
    setsid();

    //4.更改路径
    if (ifchdir = true)
        chdir(defaultPwd);

    //5.关闭或者重定向文件描述符
    if (ifclose = true)
    {
        close(0);
        close(1);
        close(2);
    }
    else 
    {
        int fd = open(devnull, O_RDWR);
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
    }
}

我们运行一下试试。

最终发现,确实变成了一个守护进程(TPGID为-1)

我们把xshell关闭周再打开试试。

重启之后,这个进程依旧再运行,此时这个进程就变成了守护进程。如果想关闭,直接使用kill命令杀死进程就可以了。

所以现在我们就可以把我们上次写的TCP服务器改成守护进程了。

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

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

相关文章

Stable Diffusion WebUI 控制网络 ControlNet 插件实现精准控图-详细教程

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 大家好&#xff0c;我是水滴~~ 本文主要介绍 Stable Diffusion WebUI 一个比较重要的插件 ControlNet&#xff08;控制网络&#xff09;&#xff0c;主…

第46篇:随机存取存储器(RAM)模块<五>

Q&#xff1a;本期我们使用Quartus软件的IP Catalog工具创建双端口RAM。 A&#xff1a;前期创建的RAM存储模块只有一个端口&#xff0c;同时为读/写操作提供地址。我们将再创建一个具有两个地址输入端口的RAM模块&#xff0c;分别为读操作和写操作提供地址。选择Basic Functio…

Ubuntu:VSCode中编译运行C++代码

版本&#xff1a;Ubuntu22.04.1 LTS 目录 1 安装VSCode并汉化 2 检查Ubuntu是否已经安装了 GCC 3 在VScode中安装C/C扩展 4 在VSCode中进行C/C配置 1 安装VSCode并汉化 安装VSCode&#xff08;参考之前博客Ubuntu&#xff1a;安装VSCode_ubuntu vscode-CSDN博客&#xff…

两数相加(链表)

2. 两数相加 - 力扣&#xff08;LeetCode&#xff09; 题解 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。…

深入理解 pytest Fixture 方法及其应用

当涉及到编写自动化测试时&#xff0c;测试框架和工具的选择对于测试用例的设计和执行非常重要。在Python 中&#xff0c;pytest是一种广泛使用的测试框架&#xff0c;它提供了丰富的功能和灵活的扩展性。其中一个很有用的功 能是fixture方法&#xff0c;它允许我们初始化测试环…

Ypay源支付最新免授权牛角魔改版

YPay是专为个人站长打造的聚合免签系统&#xff0c;拥有卓越的性能和丰富的功能。采用全新轻量化的界面UI&#xff0c;让您可以更加方便快捷地解决知识付费和运营赞助的难题。同时&#xff0c;它基于高性能的ThinkPHP 6.1.2 Layui PearAdmin架构&#xff0c;提供实时监控和管…

【JavaWeb】Day47.Mybatis基础操作——删除

Mybatis基础操作 需求 准备数据库表 emp 创建一个新的springboot工程&#xff0c;选择引入对应的起步依赖&#xff08;mybatis、mysql驱动、lombok&#xff09; application.properties中引入数据库连接信息 创建对应的实体类 Emp&#xff08;实体类属性采用驼峰命名&#xf…

反转二叉树(力扣226)

解题思路&#xff1a;用队列进行前序遍历的同时把节点的左节点和右节点交换 具体代码如下&#xff1a; class Solution { public:TreeNode* invertTree(TreeNode* root) {if (root NULL) return root;swap(root->left, root->right); // 中invertTree(root->left)…

2022年团体程序设计天梯赛-总决赛 L1 -L2

目录 L1-1 今天我要赢 L1-2 种钻石 L1-3 谁能进图书馆 L1-4 拯救外星人 L1-5 试试手气 L1-6 斯德哥尔摩火车上的题 L1-7 机工士姆斯塔迪奥 L1-8 静静的推荐 L2-1 插松枝 L2-2 老板的作息表 L2-3 龙龙送外卖 L2-4 大众情人 L1-1 今天我要赢 分数 5 2018 年我们曾经出…

时间同步服务器的搭建

1.配置server主机&#xff1a; ①server主机的主机名称为 ntp_server.example.com reboot重启 ②server主机的IP为&#xff1a; 172.25.254.100 ③server主机的时间为1984-11-11 11&#xff1a;11&#xff1a;11 先关闭时间同步服务 设置时间为1984-11-11 11&#xff1a;11&…

vue3父组件使用子组件方法

问题 关于父组件调用子组件方法是比较常见的情况&#xff0c;vue2中使用比较简单&#xff0c;那么vue3 中如何使用呢&#xff1f; 想要的效果&#xff1a; vue2 中调用子组件方法 先看下vue2中如何调用的&#xff0c;代码如下&#xff1a; // child.vue <template>&…

Linux系统的引导过程与服务控制

目录 一、Linux操作系统引导过程 二、Linux系统服务控制 系统初始化进程 三、运行级别切换 *运行级别及切换 Linux系统的运行级别 四、优化开机自动加载服务 五、修复MBR扇区故障 一、Linux操作系统引导过程 主要步骤 开机自检&#xff1a; 检测硬件设备&#…

Matlab软件使用教学

1. Matlab简介 Matlab&#xff08;Matrix Laboratory的缩写&#xff09;是一种由MathWorks公司开发的数值计算和可视化编程环境。它广泛应用于工程、科学研究、数学和教育等领域&#xff0c;因其强大的计算能力和丰富的工具箱而受到青睐。 2. 安装与启动 安装&#xff1a;从M…

Delphi Xe 10.3 钉钉SDK开发——审批流接口(获取表单ProcessCode)

开发钉钉审批流时&#xff0c;需要用到钉钉表单的Processcode&#xff0c;有两种方法 &#xff1a; 一、手动获取&#xff1a; 管理员后台——审批——找到对应的表单&#xff1a;如图&#xff1a; ProcessCode后面就是了&#xff01; 二、接口获取&#xff1a;今天的重点&a…

精致摄影网站模板 Bootstrap4

目录 一.前言 二.展示 三.下载链接 一.前言 这是一个相机摄影网站。网站结构包括以下部分&#xff1a; 导航栏部分&#xff1a;位于页面顶部&#xff0c;包含了Logo和若干导航链接&#xff0c;如Home、About、Gallery、Services、Testimonial和Contact。 横幅部分&#xff…

CSS文本属性与字体属性

目录 文本属性 文本颜色 文本对齐 修饰文本 文本缩进 行高 字体属性 字体系列 字体大小 字体粗细 字体样式 字体/文本综合属性写法 Chrome调试工具的使用 文本属性 文本颜色 在CSS中使用color 属性用于定义文本的颜色&#xff0c;使用background-color设置一个盒…

VUE3 + Elementui-Plus 之 树形组件el-tree 一键展开(收起);一键全选(不全选)

需求&#xff1a; 产品要求权限树形结构添加外部复选框进行全部展开或收起&#xff1b;全选或不全选。 实现步骤&#xff1a; tree组件部分&#xff1a; <div class"role-handle"><div>权限选择(可多选)</div><div><el-checkbox v-mode…

micropython开发与实战阅读笔记

对本文的一些说明 本文来源于阅读《MicroPython开发与实战》时所做的笔记&#xff0c;这本书不是很厚&#xff0c;所以内容也不是很全面&#xff0c;但作为一个入门工具书还是够的&#xff0c;再由于本人不是这方面的大佬&#xff0c;也不是这个专业的&#xff0c;所做的笔记也…

C++ UML 类图介绍与设计

1 类图概述 UML(Unified Modeling Language)&#xff0c;即统一建模语言&#xff0c;是用来设计软件的可视化建模语言。它的特点是简单、统一、图形化、能表达软件设计中的动态与静态信息。UML从目标系统的不同角度出发&#xff0c;定义了用例图、类图、对象图、状态图、活动图…

C++ stl容器list的底层模拟实现

目录 前言&#xff1a; 1.创建节点 2.普通迭代器的封装 3.反向迭代器的封装 为什么要对正向迭代器进行封装&#xff1f; 4.const迭代器 5.构造函数 6.拷贝构造 7.赋值重载 8.insert 9.erase 10.析构 11.头插头删&#xff0c;尾插尾删 12.完整代码简单测试 总结&…