Linux守护进程
进程组和会话在 UNIX 系统中是非常重要的概念,特别是在进行作业控制和终端会话管理时。下面是关于进程组和会话的详细解释:
进程组(Process Group)
-
定义与作用:
- 进程组是一个或多个进程的集合,这些进程通常是从同一个作业启动的,共享同一个进程组标识符(PGID)。例如,一个复杂的命令行管道操作(如
cmd1 | cmd2)中的所有进程可以属于同一个进程组。 - 进程组使得操作系统可以方便地对一组相关进程执行操作,如发送信号。
- 进程组是一个或多个进程的集合,这些进程通常是从同一个作业启动的,共享同一个进程组标识符(PGID)。例如,一个复杂的命令行管道操作(如
-
进程组首进程:
- 每个进程组有一个首进程,这是创建该组的进程,其进程 ID(PID)同时作为该进程组的 ID。
- 进程组首进程在创建时设置组 ID,并可以通过特定的系统调用(如
setpgid())修改自己或其他进程的进程组归属。
-
生命周期:
- 进程组的生命周期从首进程创建该组开始,直到最后一个进程退出该组时结束。
- 进程可能会因为终止自身或被其他信号杀死而离开进程组,或者它可以调用系统函数切换到另一个进程组。
会话
会话(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 系统中一个非常核心的概念,对于系统的稳定运行和服务的持续提供至关重要。这些进程通常是在系统启动时启动,并在整个系统运行期间持续运行,直到系统关闭。下面详细解释守护进程的特征和其实现方法:
特征
-
长生命周期:
- 守护进程通常在系统启动时创建,例如通过系统的初始化系统(如
systemd、init)自动启动。 - 它们不会像交互式用户进程那样在任务完成后退出,而是一直运行,直到系统关闭。
- 守护进程通常在系统启动时创建,例如通过系统的初始化系统(如
-
在后台运行:
- 守护进程通常在后台运行,不与任何用户直接交互。
- 它们通常不拥有控制终端,这防止了终端信号(如 SIGINT 或 SIGQUIT)意外中断它们的运行。
-
服务性质:
- 守护进程通常执行周期性任务或等待特定事件的发生,例如监听网络请求或文件系统变化。
- 例如,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 系统中是非常重要的概念,特别是在进行作业控制和终端会话管理时。下面是关于进程组和会话的详细解释: 进程组(Process Group) 定义与作用: 进程组是一个或多个进程的集合,这些进程通常…...
HarmonyOS 应用开发——入门
首先当然是华为的官方文档了,要认真学习: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/start-overview-0000001478061421-V2 不想花时间看,可以看我下面总结的干货,哈哈 第一个问题:stage架构和fa架构的区…...
开源免费的发票识别OCR应用:Invoice
Invoice:轻松识别,发票电子化扫描烦恼消- 精选真开源,释放新价值。 概览 Invoice 是github社区上一个采用开源许可协议发布的增值税发票光学字符识别(OCR)解决方案项目。该项目不仅集成了预训练的高级模型,…...
关于Docker alpine
1.拉取alpine镜像 docker pull alpine 2.运行镜像成为容器 docker run -it --rm alpine sh (--rm标志确保容器在退出时被自动删除。) 3.容器建立后,运行 docker exec -it <container_id> sh 4.进入容器里的 alpine环境 ①.配置安装源 cat >/etc…...
【Elasticsearch运维系列】Elasticsearch7.12.1启动指定版本JDK:你学废了吗?
一、背景 一套生ES集群,版本为7.12.1,近期频繁告警,频繁出现索引分片异常,索引状态异常,导致应用无法正常写入ES,另外,也经常出现节点掉问题。通过分析相关ES日志,显示和当前JAVA G…...
思通数科大模型在智能数据查询系统中的深度应用:销售数据分析的革新
在企业决策支持系统中,销售数据分析占据着举足轻重的地位。思通数科的大模型技术,结合自然语言处理(NLP)和机器学习,为智能数据查询系统提供了强大的分析能力。本文将详细描述思通数科大模型在销售数据分析中的应用&am…...
上位机图像处理和嵌入式模块部署(树莓派4b和qt应用全屏占有)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 我们都知道,嵌入式应用一般都是为了某一个特定应用而存在的。也就是说,和pc不同,这个嵌入式板子一般都是为了解…...
QT:QT窗口(一)
文章目录 菜单栏创建菜单栏在菜单栏中添加菜单创建菜单项添加分割线 工具栏创建工具栏设置停靠位置创建工具栏的同时指定停靠位置使用QToolBar类提供的setAllowedAreas函数来设置停靠位置 设置浮动属性设置移动属性 状态栏状态栏的创建在状态栏中显示实时消息在状态栏中显示永久…...
matlab例题大全
1.第1章 MATLAB系统环境 1.1 注:plot函数为画图函数。例plot(x1,y1,:,x2,y2,*); 1.2 注:root为求根函数。p为方程变量前面系数矩阵。 1.3 注: 2*x3y-1*z 2; 8*x2*y3*z 4; 45*x3*y9*z 23 求:x,y,z的…...
SwiGLU激活函数
SwiGLU激活函数已经成为LLM的标配了。它是GLU的变体,公式如下: 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的慢查询时,通常需要结合多个方面进行分析和优化,包括索引优化、SQL语句重构、数据库结构调整等。下面,我将通过一个例子来说明如何优化MySQL的慢查询,包括多表关联和条件查询。 假设我们有一个简化的电子商务系统…...
开源数据可视化大屏对接表单数据实践!
如果你需要一个表单系统,进行数据收集;可以使用tduck填鸭进行私有化部署,进行表单制作,完成数据收集。 在实际业务中,往往需要将收集的数据进行展示或分析;此时就可以使用表单数据推送到TReport中…...
08.图形化界面字体问题处理
图形化界面字体问题处理 发现图形存在乱码,不显示文字 zabbix服务器的字符集所在的路径下: /usr/share/zabbix/assets/fonts 将本地windows系统的字体进行上传,选择一个自己喜欢的字体 上传到系统路径下并且直接覆盖掉 回到web浏览器界面…...
【代码随想录算法训练营第37期 第二天 | LeetCode977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II】
代码随想录算法训练营第37期 第二天 | LeetCode977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II 一、977.有序数组的平方 解题代码C: class Solution { public:vector<int> sortedSquares(vector<int>& nums) {int len nums.size();fo…...
Java:Servlet详解
目录 一、什么是Servlet 二、Servlet原理 Servlet的生命周期 三、 Servlet注释 WebServlet 一、什么是Servlet Servlet是JavaWeb开发的一种技术,Servlet程序需要部署在Servlet容器(服务端)中才能运行,常见的Servlet容器有Tom…...
Oracle存储过程怎么定义类并继承
在Oracle数据库中,存储过程(Stored Procedure)是用于执行特定功能的预编译的SQL代码块。然而,Oracle的存储过程并不直接支持面向对象的编程概念,如类(Class)和继承(Inheritance&…...
14_Scala面向对象编程_属性
文章目录 属性1.类中属性声明2.系统默认赋值3.BeanProperty4.整体代码如下 属性 1.类中属性声明 // 1.给Scala声明属性;var name :String "zhangsan"val age :Int 302.系统默认赋值 scala由于初始化变量必须赋值,为了解决此问题可以采…...
什么是网页反作弊
在搜索引擎技术中,网页反作弊是指一种防止网页排名被恶意操纵的技术。搜索引擎会根据特定的算法来评估网页的相关性和质量,以决定其在搜索结果中的排名。然而,有些人可能会尝试通过各种不正当的手段来提高自己网页的排名,这被称为…...
MAVEN打包JAR启动执行manifest
当您使用Maven进行项目打包,特别是需要创建一个可执行的JAR文件时,确保JAR文件的MANIFEST.MF中包含正确的Main-Class属性是非常重要的。这个属性告诉Java运行时环境哪个类包含main方法,作为应用程序的入口点。 如果您发现生成的JAR文件不包含…...
JavaEE 多线程详细讲解(1)
1.线程是什么 (shift F6)改类名 1.1.并发编程是什么 (1)当前的CPU,都是多核心CPU (2)需要一些特定的编程技巧,把要完成的仍无,拆解成多个部分,并且分别让…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
