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

Linux笔记---进程间关系与守护进程

1. 进程组

在操作系统中,进程组(Process Group) 是由一个或多个相关进程组成的集合,用于简化对多个关联进程的统一管理。它是 Unix/Linux 系统中进程组织的重要概念,主要为了方便信号传递、作业控制等操作。

每个进程组由唯一的 进程组 ID(PGID) 标识。通常,进程组的创建者(称为 “组长进程”)的进程 ID(PID)会作为该进程组的 PGID(即 PGID = 组长进程的PID)。

什么是有关联的进程呢?有父子关系的进程、通过管道相连的进程……这些在操作系统层面上有关联,需要相互协作的进程就叫有关联的进程。

例如,我们在命令行中输入如下的命令:

sleep 1000 | sleep 2000 | sleep 3000

这三个sleep进程之间就是有关联的进程,我们使用ps命令查看这三个进程的信息:

我们可以发现,三者的PGID是相同的,这就代表他们是一个进程组的。其中,sleep 1000的PID和PGID是相同的,这就代表它是这个进程组的组长。

当一个进程没有与其他进程产生关联时,它自己就构成一个进程组,同时也是组长。

进程组的主要作用:

  • 批量信号处理:可以向整个进程组发送信号(而非单个进程),简化对关联进程的统一控制。例如,在终端中按下 Ctrl+C 时,内核会向前台进程组的所有进程发送 SIGINT 信号(在上面的例子当中,如果我们按下Ctrl+C,三个sleep进程会一起被终止)。
  • 作业控制:shell 利用进程组实现 “前台 / 后台作业” 管理。例如,通过 & 让命令在后台运行时,shell 会为其创建一个独立的进程组。一个进程组成为前台进程组时,本质上是组长进程成为前台进程,并与终端交互。

2. 会话

在 Unix/Linux 操作系统中,会话(Session) 是比进程组更高一级的进程组织单位,由一个或多个进程组组成,主要用于管理进程与控制终端的关联,是作业控制和终端交互的核心机制。

每个会话由唯一的 会话 ID(SID) 标识,通常以创建会话的进程(称为 “会话首进程”)的 PID 作为 SID(即 SID = 会话首进程的PID)。

用户登录(或者说开启一个终端),操作系统就会为用户创建一个会话,这个会话就关联到该终端。shell程序(bash)就作为会话的首进程:

而在某个终端当中启动的进程(组)就属于这个终端关联的会话:

当用户退出时(关闭终端),对应的会话就会被关闭,其中的进程组也就随之被全部终止。

一个会话只关联一个终端,所以会话当中的进程组就可以分为两类:

  1. 一个前台进程组
  2. 若干后台进程组

会话的主要作用就是进行终端资源管理:会话将进程组与控制终端绑定,确保终端资源(输入、输出、信号)被有序分配给前台进程组,避免多个进程同时争抢终端。

会话的生命周期与属于其的进程组相关,当会话中的进程组全部终止之后,会话就会结束。

若会话关联了控制终端,终端关闭时内核会向会话首进程发送 SIGHUP 信号(默认导致进程终止),并向前台进程组发送 SIGHUP 和 SIGCONT 信号。若这些进程因此终止,且会话中无其他进程组,则会话结束。

3. 守护进程

在 Unix/Linux 操作系统中,守护进程(Daemon) 是一类在后台长期运行的特殊进程,通常用于提供系统服务或周期性执行任务,不与用户直接交互,完全脱离终端控制。

特点:

  • 后台运行:守护进程不占用终端,用户无法通过终端直接输入指令与其交互,其运行状态也不会干扰终端的正常使用。
  • 脱离终端:守护进程与启动它的终端完全脱离,即使终端关闭(如用户退出登录),守护进程也能继续运行(不会收到终端关闭产生的 SIGHUP 信号)。
  • 生命周期长:守护进程通常随系统启动而启动,随系统关闭而终止,在整个系统运行期间持续提供服务(如 Web 服务器 nginx、数据库服务 mysqld 等)。
  • 无控制终端:守护进程没有控制终端(tty),其标准输入、输出、错误输出通常会被重定向到 /dev/null 或日志文件。

守护进程是系统服务的核心载体,常见用途包括:

  • 网络服务:如 nginx(Web 服务器)、sshd(远程登录服务)、dnsmasq(DNS 服务)等,持续监听网络请求并响应。
  • 系统管理:如 crond(定时任务服务)、systemd(系统进程管理器)等,负责周期性任务或系统资源管理。
  • 后台处理:如日志收集进程、数据同步进程等,在后台默默处理系统或应用数据。

创建守护进程的核心就是让某个进程成为一个新会话的首进程。如此一来,只要守护进程不退出,会话就不会结束,守护进程就能长期存在。

3.1 setsid系统调用

在 Unix/Linux 系统中,setsid() 是一个核心的系统调用,主要用于创建一个新的会话,并让调用进程成为该会话的会话首进程。它是实现创建守护进程(进程脱离终端控制)的关键函数。

#include <unistd.h>
pid_t setsid(void);

返回值

  1. 成功时,返回新会话的 ID(即调用进程的 PID)。
  2. 失败时,返回 -1,并设置 errno 指示错误原因(最常见的错误是 EPERM:调用进程已是某个进程组的组长)。

setsid() 有一个重要限制:调用进程不能是任何进程组的组长。 如果调用进程恰好是进程组组长(例如,直接在主进程中调用 setsid()),函数会调用失败(返回 -1,errno=EPERM)。

解决这个限制条件的常见做法就是在调用setsid前先调用fork函数,并让父进程立即退出。

3.2 创建守护进程的标准流程

  1. 创建子进程,父进程退出:为调用setsid()做准备。
  2. 创建新会话(setsid():脱离原终端的控制(原终端不再与该会话关联)。
  3. 再次 fork 并退出父进程(可选但推荐):孙子进程不再是会话首进程,确保它无法再打开新的控制终端(只有会话首进程能关联终端)。
  4. 改变工作目录(可选):将工作目录切换到根目录(/)或特定目录(如 /var/run),避免守护进程占用某个可卸载的文件系统(如挂载的 U 盘)。
  5. 输入输出重定向(可选):将继承的所有文件描述符(stdin、stdout、stderr 等)重定向到 /dev/null(“黑洞” 设备,丢弃所有输入输出)。
#pragma once
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>// 将进程切换为守护进程
int Daemon(int nochdir, int noclose)
{// 忽略管道关闭和子进程退出signal(SIGCHLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);// 切换为孙子进程, 因为进程组组长无法调用setsidif (fork() > 0) exit(0);// 设置为独立的会话组if (setsid() == -1){return -1;}// 切换为孙子进程(不是新会话的首进程), 确保无法打开新的控制终端if (fork() > 0) exit(0);// 将工作目录切换为根目录if (!nochdir){chdir("/");}// 将标准输入、输出、错误重定向到/dev/nullif (!noclose){int fd = ::open("/dev/null", O_RDWR);if (fd == -1){return -1;}else{dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);}}return 0;
}

当然,操作系统也为我们提供了对应的接口:

#include <unistd.h>
int daemon(int nochdir, int noclose);

上面的接口就是仿照这个接口设计的,参数与返回值的含义都一样,就不过多介绍了。


文章转载自:

http://A5qAaPVa.mLzyx.cn
http://jq3wCzrB.mLzyx.cn
http://7Bad0Y0i.mLzyx.cn
http://DJXFuvyK.mLzyx.cn
http://BBIQYfRK.mLzyx.cn
http://w0YBVy3M.mLzyx.cn
http://owQWtKEh.mLzyx.cn
http://CCbGeOZN.mLzyx.cn
http://ubefJQTl.mLzyx.cn
http://XZHQLetZ.mLzyx.cn
http://WCooKWpw.mLzyx.cn
http://zeu19kBP.mLzyx.cn
http://kZwfzcXB.mLzyx.cn
http://Yj8mLZuw.mLzyx.cn
http://VeCpeJyX.mLzyx.cn
http://tErdh1oL.mLzyx.cn
http://mU9pEpkP.mLzyx.cn
http://SWVI2Qqe.mLzyx.cn
http://36AsqagE.mLzyx.cn
http://QJHJ6rRW.mLzyx.cn
http://triVGBo1.mLzyx.cn
http://8dNePs2M.mLzyx.cn
http://0UNnngbP.mLzyx.cn
http://WLOL2GHA.mLzyx.cn
http://1PkNgfAc.mLzyx.cn
http://0JyaEOgu.mLzyx.cn
http://9vyyQkX1.mLzyx.cn
http://M1lxozcm.mLzyx.cn
http://p69oZViP.mLzyx.cn
http://lME8XfXK.mLzyx.cn
http://www.dtcms.com/a/374458.html

相关文章:

  • 详细:虚拟机 + Linux 环境搭建 + Oracle 11.2.0 EE 安装全流程
  • 思利普科技:用BCG心冲击技术重新定义睡眠监测,掀起床垫行业智能化革命
  • 2025世界智博会,揭幕AI触手可及的科幻生活
  • 探索 CSS 3D 属性:从基础到炫酷动画案例
  • “从零到一:使用GitLab和Jenkins实现自动化CI/CD流水线”
  • 考研408《计算机组成原理》复习笔记,第六章(1)——总线概念
  • adb的常用命令
  • 设计模式:策略模式
  • 【华为OD】数字游戏
  • 分享:一种为蓝牙、WIFI、U段音频发射设备提供ARC回传数字音频桥接功能的方案
  • 【设计模式】 外观模式
  • 在 JavaScript中使用msgpack-lite 和zlib实现大数据文件的压缩和读取
  • 医疗连续体机器人模块化控制界面设计与Python库应用研究(中)
  • 【数据库】Redis详解:内存数据库与缓存之王
  • OpenCV 图像处理实战:从图像金字塔到直方图分析
  • MongoDB 安全加固:构建企业级纵深防御体系——用户权限管理与 TLS 加密配置详解
  • 为什么苹果签名经常会掉签?
  • http basic认证流程
  • Docker 存储卷(Volume)核心概念、类型与操作指南
  • 【iOS】 单例模式
  • Matlab机器人工具箱使用4 蒙特卡洛法绘制工作区间
  • 【华为OD】环中最长子串2
  • 08 docker搭建大数据集群
  • 【华为OD】微服务的集成测试
  • Tool | UI/BI类网址收录
  • 计算机视觉(opencv)——基于模板匹配的身份证号识别系统
  • 腾讯推出AI CLI工具CodeBuddy,国内首家同时支持插件、IDE和CLI三种形态的AI编程工具厂商
  • 前后端联调时出现的一些问题记录
  • 网络编程;套接字;TCP通讯;UDP通讯;0909
  • 最后一公里文件传输难题Localsend+cpolar破解