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

Linux守护进程

进程组和会话在 UNIX 系统中是非常重要的概念,特别是在进行作业控制和终端会话管理时。下面是关于进程组和会话的详细解释:

进程组(Process Group)

  1. 定义与作用

    • 进程组是一个或多个进程的集合,这些进程通常是从同一个作业启动的,共享同一个进程组标识符(PGID)。例如,一个复杂的命令行管道操作(如 cmd1 | cmd2)中的所有进程可以属于同一个进程组。
    • 进程组使得操作系统可以方便地对一组相关进程执行操作,如发送信号。
  2. 进程组首进程

    • 每个进程组有一个首进程,这是创建该组的进程,其进程 ID(PID)同时作为该进程组的 ID。
    • 进程组首进程在创建时设置组 ID,并可以通过特定的系统调用(如 setpgid())修改自己或其他进程的进程组归属。
  3. 生命周期

    • 进程组的生命周期从首进程创建该组开始,直到最后一个进程退出该组时结束。
    • 进程可能会因为终止自身或被其他信号杀死而离开进程组,或者它可以调用系统函数切换到另一个进程组。

会话

会话(session)管理是 UNIX 系统中处理进程组和终端交互的重要机制。这里提供对您提到的各个点的更深入的解释:

会话首进程与会话 ID
  • 会话首进程:创建新会话的进程自动成为该会话的首进程。这通常发生在用户登录时或者当一个进程通过调用 setsid() 系统调用来显式创建一个新会话。
  • 会话 ID:新会话的创建同时生成一个新的会话标识符(session ID),该标识符等于该会话首进程的进程 ID (PID)。新创建的进程会继承其父进程的会话 ID,除非它们显式地创建或加入一个新的会话。
控制终端
  • 建立控制终端:控制终端通常在会话首进程首次打开一个终端设备时被建立。控制终端是会话中进程交互的主要方式,如读取用户的键盘输入和输出信息到屏幕。
  • 终端与会话的关系:一个终端设备在任一时间点最多只能是一个会话的控制终端。一旦终端被某个会话首次占用,其他会话将无法将其设置为控制终端。
前台与后台进程组
  • 前台进程组:在任何给定时刻,会话中只有一个进程组可以成为前台进程组。这个组的进程可以直接从控制终端接收输入,这对于交互式应用非常关键。
  • 后台进程组:不在前台的进程组称为后台进程组。这些进程组不能直接从控制终端读取输入,这样设计可以避免输入冲突和管理复杂度。
信号处理与终端字符
  • 终端字符生成信号:用户在控制终端输入特定的键(如 Ctrl+C)会生成信号(如 SIGINT),这些信号会被发送到前台进程组的所有进程。这允许用户可以直接与运行在前台的进程组交互,例如中断正在执行的命令。
控制进程
  • 会话首进程的角色:一旦控制终端的连接建立,会话首进程也成为控制进程。这意味着它负责处理来自控制终端的信号和可能的终端断开(如用户注销)。

通过这些机制,UNIX 系统提供了强大的工具来管理和控制多个进程和它们的交互,这对于构建稳定和可管理的多用户环境是必要的。

进程组、会话、控制终端之间的关系

在 UNIX 系统中,进程组、会话和控制终端之间的关系是协调进程之间通信和控制的关键机制。这些概念相互作用,支持复杂的作业控制和会话管理,特别是在多用户环境中。下面是这些概念之间关系的详细解释:

1. 进程组(Process Group)

进程组是一种逻辑分组,用于将一系列相关的进程组织在一起,以便于统一管理。通常情况下,这些进程是从同一个命令行启动的,比如一个 shell 脚本中的多个命令。进程组内的每个进程都共享同一个进程组标识符(PGID),使得操作系统可以方便地对整个组发送信号。

2. 会话(Session)

会话是一或多个进程组的更高级别的集合。每个会话可以包含多个进程组,包括前台和后台进程组。会话通常在用户登录时开始,用户的登录 shell 成为会话首进程,并且会创建一个新的会话。这个会话首进程有权申请或分配一个控制终端。

3. 控制终端(Controlling Terminal)

控制终端是会话首进程与用户交互的界面。它通常是一个物理或虚拟的终端设备(如终端窗口)。会话首进程在首次打开一个终端设备时,该设备成为该会话的控制终端。控制终端可以被用来向会话中的进程发送信号(例如,当用户按下 Ctrl+C 时发送 SIGINT)。

关系概述:
  • 会话与进程组:会话是进程组的容器,可以包含多个进程组。在一个会话中,可以指定一个进程组作为前台进程组,其他的则作为后台进程组。前台进程组可以接收来自控制终端的输入,而后台进程组则不能。
  • 会话与控制终端:会话首进程可以为会话获取一个控制终端,这个终端成为整个会话及其所有进程组的交互中心。控制终端可以被用来管理会话中的进程,如发送中断信号。
  • 进程组与控制终端:在有控制终端的会话中,只有前台进程组可以直接从控制终端接收输入和处理特定的控制信号(如 SIGINT)。后台进程组则被限制,不能直接读取控制终端的输入,以防止输入输出冲突。

这种层次和关系的设置使得 UNIX 系统能够有效地管理多任务操作,特别是在多用户和网络环境中,提供了高度的灵活性和控制能力。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

进程组、会话操作函数

在 UNIX 和类 UNIX 系统中,操作进程组和会话的一些核心函数允许程序员在运行时管理进程的组和会话属性。这些函数非常重要,因为它们提供了控制进程如何与操作系统和其他进程交互的能力。

1. 获取和设置进程组
pid_t getpgrp(void);
  • 描述:此函数返回当前进程的进程组 ID。
  • 返回值:返回调用进程的进程组 ID。
pid_t getpgid(pid_t pid);
  • 描述:获取指定进程的进程组 ID。如果 pid 为 0,则返回调用进程的进程组 ID。
  • 参数
    • pid:进程标识符。
  • 返回值:成功时返回进程组 ID,失败时返回 -1 并设置 errno。
int setpgid(pid_t pid, pid_t pgid);
  • 描述:设置指定进程的进程组 ID。这个函数可以用来将进程 pid 加入到进程组 pgid,或者创建一个新的进程组(如果 pid 等于 pgid)。
  • 参数
    • pid:要更改进程组的进程的 ID,如果 pid 是 0,则表示调用进程。
    • pgid:新的进程组 ID,如果 pgid 是 0,则 pid 指定的进程将成为新进程组的首进程。
  • 返回值:成功时返回 0,失败时返回 -1 并设置 errno。

2. 获取和设置会话

pid_t getsid(pid_t pid);
  • 描述:获取指定进程的会话 ID。如果 pid 为 0,则返回调用进程的会话 ID。
  • 参数
    • pid:进程标识符。
  • 返回值:成功时返回会话 ID,失败时返回 -1 并设置 errno。
pid_t setsid(void);
  • 描述:创建一个新的会话,并设置当前进程为该会话的首进程和进程组首进程。当前进程不能是进程组的领头进程。
  • 返回值:成功时返回新会话的会话 ID,失败时返回 -1 并设置 errno。

注意事项

  • 在使用 setpgid()setsid() 时,要注意进程间的权限和状态,因为这些调用可能受到限制,特别是在已经拥有子进程或已属于某个进程组的情况下。
  • 调用 setsid() 时,如果调用者已是某个进程组的领头进程,则该调用会失败。这是为了防止一个已有控制终端的进程逃避终端产生的信号。

这些函数提供了在 UNIX 类操作系统中管理和控制进程组和会话的基本机制,对于实现作业控制、守护进程以及终端会话管理等功能至关重要。

守护进程

守护进程(Daemon process)是 Linux 系统中一个非常核心的概念,对于系统的稳定运行和服务的持续提供至关重要。这些进程通常是在系统启动时启动,并在整个系统运行期间持续运行,直到系统关闭。下面详细解释守护进程的特征和其实现方法:

特征
  1. 长生命周期

    • 守护进程通常在系统启动时创建,例如通过系统的初始化系统(如 systemdinit)自动启动。
    • 它们不会像交互式用户进程那样在任务完成后退出,而是一直运行,直到系统关闭。
  2. 在后台运行

    • 守护进程通常在后台运行,不与任何用户直接交互。
    • 它们通常不拥有控制终端,这防止了终端信号(如 SIGINT 或 SIGQUIT)意外中断它们的运行。
  3. 服务性质

    • 守护进程通常执行周期性任务或等待特定事件的发生,例如监听网络请求或文件系统变化。
    • 例如,HTTP 服务器(如 Apache 的 httpd)、邮件服务器(如 postfix)和文件服务器(如 smbd)都是典型的守护进程。
实现守护进程

这个过程是在 UNIX 和 Linux 系统中常用的模式,用于创建独立于控制终端的后台服务。以下是如何执行这个转换的详细步骤,包括其中涉及的各个系统调用和目的:

1.创建子进程并结束父进程

这个步骤确保了新的守护进程不是一个会话领导者,从而可以调用 setsid() 创建新会话。

pid_t pid = fork();
if (pid < 0) {// 处理错误exit(EXIT_FAILURE);
}
if (pid > 0) {// 父进程直接退出exit(EXIT_SUCCESS);
}
2. 创建新会话

子进程调用 setsid() 创建一个新的会话,成为会话的领导者,脱离任何控制终端。

if (setsid() < 0) {// 处理错误exit(EXIT_FAILURE);
}
3. 清除文件创建掩码(umask)(非必须)

设置 umask 为 0 确保守护进程创建的任何文件和目录都有适当的访问权限。

umask(0);
4. 更改当前工作目录

将当前工作目录改为根目录 /,这可以防止守护进程阻止卸载文件系统。

if (chdir("/") < 0) {// 处理错误exit(EXIT_FAILURE);
}
5. 关闭所有继承的文件描述符

这可以防止守护进程无意中保持打开的文件描述符,可能导致资源泄露或不必要的行为。

int x;
for (x = sysconf(_SC_OPEN_MAX); x >= 0; x--) {close(x);
}
6. 重定向标准文件描述符到 /dev/null

关闭了标准输入、输出和错误(文件描述符 0, 1, 2)后,常见做法是打开 /dev/null 并用 dup2() 使得这些描述符指向 /dev/null。这样,任何尝试读写这些文件描述符的操作都不会有任何效果。

int fd = open("/dev/null", O_RDWR);
dup2(fd, 0); // STDIN
dup2(fd, 1); // STDOUT
dup2(fd, 2); // STDERR
7. 执行核心业务逻辑

在完成所有的设置后,守护进程可以开始执行其核心功能,如周期性检查、处理请求等。

while (1) {// 执行任务sleep(1); // 休眠是为了模拟周期性任务
}

以上步骤创建了一个完全独立的守护进程,它在系统后台安静地运行,几乎不受用户会话影响,适用于需要长时间运行并且不需要用户交互的服务。这种类型的进程是服务器和服务架构的基础。

案例
/*写一个守护进程,每隔2s获取一下系统时间,将这个时间写入到磁盘文件中。
*/#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>void work(int num) {// 捕捉到信号之后,获取系统时间,写入磁盘文件time_t tm = time(NULL);struct tm * loc = localtime(&tm);// char buf[1024];// sprintf(buf, "%d-%d-%d %d:%d:%d\n",loc->tm_year,loc->tm_mon// ,loc->tm_mday, loc->tm_hour, loc->tm_min, loc->tm_sec);// printf("%s\n", buf);char * str = asctime(loc);int fd = open("time.txt", O_RDWR | O_CREAT | O_APPEND, 0664);write(fd ,str, strlen(str));close(fd);
}int main() {// 1.创建子进程,退出父进程pid_t pid = fork();if(pid > 0) {exit(0);}// 2.将子进程重新创建一个会话,新的会话会脱离原来的控制终端setsid();// 3.设置掩码umask(022);// 4.更改工作目录chdir("/home/nowcoder/");// 5. 关闭、重定向文件描述符int fd = open("/dev/null", O_RDWR);dup2(fd, STDIN_FILENO);dup2(fd, STDOUT_FILENO);dup2(fd, STDERR_FILENO);// 6.业务逻辑// 捕捉定时信号struct sigaction act;act.sa_flags = 0;act.sa_handler = work;sigemptyset(&act.sa_mask);sigaction(SIGALRM, &act, NULL);struct itimerval val;val.it_value.tv_sec = 2;val.it_value.tv_usec = 0;val.it_interval.tv_sec = 2;val.it_interval.tv_usec = 0;// 创建定时器setitimer(ITIMER_REAL, &val, NULL);// 不让进程结束while(1) {sleep(10);}return 0;
}

相关文章:

Linux守护进程

进程组和会话在 UNIX 系统中是非常重要的概念&#xff0c;特别是在进行作业控制和终端会话管理时。下面是关于进程组和会话的详细解释&#xff1a; 进程组&#xff08;Process Group&#xff09; 定义与作用&#xff1a; 进程组是一个或多个进程的集合&#xff0c;这些进程通常…...

HarmonyOS 应用开发——入门

首先当然是华为的官方文档了&#xff0c;要认真学习: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/start-overview-0000001478061421-V2 不想花时间看&#xff0c;可以看我下面总结的干货&#xff0c;哈哈 第一个问题&#xff1a;stage架构和fa架构的区…...

开源免费的发票识别OCR应用:Invoice

Invoice&#xff1a;轻松识别&#xff0c;发票电子化扫描烦恼消- 精选真开源&#xff0c;释放新价值。 概览 Invoice 是github社区上一个采用开源许可协议发布的增值税发票光学字符识别&#xff08;OCR&#xff09;解决方案项目。该项目不仅集成了预训练的高级模型&#xff0c…...

关于Docker alpine

1.拉取alpine镜像 docker pull alpine 2.运行镜像成为容器 docker run -it --rm alpine sh (--rm标志确保容器在退出时被自动删除。) 3.容器建立后&#xff0c;运行 docker exec -it <container_id> sh 4.进入容器里的 alpine环境 ①.配置安装源 cat >/etc…...

【Elasticsearch运维系列】Elasticsearch7.12.1启动指定版本JDK:你学废了吗?

一、背景 一套生ES集群&#xff0c;版本为7.12.1&#xff0c;近期频繁告警&#xff0c;频繁出现索引分片异常&#xff0c;索引状态异常&#xff0c;导致应用无法正常写入ES&#xff0c;另外&#xff0c;也经常出现节点掉问题。通过分析相关ES日志&#xff0c;显示和当前JAVA G…...

思通数科大模型在智能数据查询系统中的深度应用:销售数据分析的革新

在企业决策支持系统中&#xff0c;销售数据分析占据着举足轻重的地位。思通数科的大模型技术&#xff0c;结合自然语言处理&#xff08;NLP&#xff09;和机器学习&#xff0c;为智能数据查询系统提供了强大的分析能力。本文将详细描述思通数科大模型在销售数据分析中的应用&am…...

上位机图像处理和嵌入式模块部署(树莓派4b和qt应用全屏占有)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 我们都知道&#xff0c;嵌入式应用一般都是为了某一个特定应用而存在的。也就是说&#xff0c;和pc不同&#xff0c;这个嵌入式板子一般都是为了解…...

QT:QT窗口(一)

文章目录 菜单栏创建菜单栏在菜单栏中添加菜单创建菜单项添加分割线 工具栏创建工具栏设置停靠位置创建工具栏的同时指定停靠位置使用QToolBar类提供的setAllowedAreas函数来设置停靠位置 设置浮动属性设置移动属性 状态栏状态栏的创建在状态栏中显示实时消息在状态栏中显示永久…...

matlab例题大全

1.第1章 MATLAB系统环境 1.1 注&#xff1a;plot函数为画图函数。例plot&#xff08;x1,y1,:,x2,y2,*&#xff09;; 1.2 注&#xff1a;root为求根函数。p为方程变量前面系数矩阵。 1.3 注&#xff1a; 2*x3y-1*z 2; 8*x2*y3*z 4; 45*x3*y9*z 23 求&#xff1a;x,y,z的…...

SwiGLU激活函数

SwiGLU激活函数已经成为LLM的标配了。它是GLU的变体&#xff0c;公式如下&#xff1a; SwiGLU ⁡ ( x , W , V , b , c , β ) Swish ⁡ β ( x W b ) ⊗ ( x V c ) \operatorname{SwiGLU}(x, W, V, b, c, \beta)\operatorname{Swish}_\beta(x Wb) \otimes(x Vc) SwiGLU(x,…...

MySQL慢查询优化

当需要优化MySQL的慢查询时&#xff0c;通常需要结合多个方面进行分析和优化&#xff0c;包括索引优化、SQL语句重构、数据库结构调整等。下面&#xff0c;我将通过一个例子来说明如何优化MySQL的慢查询&#xff0c;包括多表关联和条件查询。 假设我们有一个简化的电子商务系统…...

开源数据可视化大屏对接表单数据实践!

如果你需要一个表单系统&#xff0c;进行数据收集&#xff1b;可以使用tduck填鸭进行私有化部署&#xff0c;进行表单制作&#xff0c;完成数据收集。 在实际业务中&#xff0c;往往需要将收集的数据进行展示或分析&#xff1b;此时就可以使用表单数据推送到TReport中&#xf…...

08.图形化界面字体问题处理

图形化界面字体问题处理 发现图形存在乱码&#xff0c;不显示文字 zabbix服务器的字符集所在的路径下&#xff1a; /usr/share/zabbix/assets/fonts 将本地windows系统的字体进行上传&#xff0c;选择一个自己喜欢的字体 上传到系统路径下并且直接覆盖掉 回到web浏览器界面…...

【代码随想录算法训练营第37期 第二天 | LeetCode977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II】

代码随想录算法训练营第37期 第二天 | LeetCode977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II 一、977.有序数组的平方 解题代码C&#xff1a; class Solution { public:vector<int> sortedSquares(vector<int>& nums) {int len nums.size();fo…...

Java:Servlet详解

目录 一、什么是Servlet 二、Servlet原理 Servlet的生命周期 三、 Servlet注释 WebServlet 一、什么是Servlet Servlet是JavaWeb开发的一种技术&#xff0c;Servlet程序需要部署在Servlet容器&#xff08;服务端&#xff09;中才能运行&#xff0c;常见的Servlet容器有Tom…...

Oracle存储过程怎么定义类并继承

在Oracle数据库中&#xff0c;存储过程&#xff08;Stored Procedure&#xff09;是用于执行特定功能的预编译的SQL代码块。然而&#xff0c;Oracle的存储过程并不直接支持面向对象的编程概念&#xff0c;如类&#xff08;Class&#xff09;和继承&#xff08;Inheritance&…...

14_Scala面向对象编程_属性

文章目录 属性1.类中属性声明2.系统默认赋值3.BeanProperty4.整体代码如下 属性 1.类中属性声明 // 1.给Scala声明属性&#xff1b;var name :String "zhangsan"val age :Int 302.系统默认赋值 scala由于初始化变量必须赋值&#xff0c;为了解决此问题可以采…...

什么是网页反作弊

在搜索引擎技术中&#xff0c;网页反作弊是指一种防止网页排名被恶意操纵的技术。搜索引擎会根据特定的算法来评估网页的相关性和质量&#xff0c;以决定其在搜索结果中的排名。然而&#xff0c;有些人可能会尝试通过各种不正当的手段来提高自己网页的排名&#xff0c;这被称为…...

MAVEN打包JAR启动执行manifest

当您使用Maven进行项目打包&#xff0c;特别是需要创建一个可执行的JAR文件时&#xff0c;确保JAR文件的MANIFEST.MF中包含正确的Main-Class属性是非常重要的。这个属性告诉Java运行时环境哪个类包含main方法&#xff0c;作为应用程序的入口点。 如果您发现生成的JAR文件不包含…...

JavaEE 多线程详细讲解(1)

1.线程是什么 &#xff08;shift F6&#xff09;改类名 1.1.并发编程是什么 &#xff08;1&#xff09;当前的CPU&#xff0c;都是多核心CPU &#xff08;2&#xff09;需要一些特定的编程技巧&#xff0c;把要完成的仍无&#xff0c;拆解成多个部分&#xff0c;并且分别让…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...