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

【Liunx】进程间关系与守护进程

1. 进程组

1.1 什么是进程组

  • 进程组是一个或多个进程的集合,每个进程除 PID 外,还属于一个进程组。
  • 每个进程组有唯一的进程组 ID(PGID),类型为pid_t(正整数)。
  • 查看方式:ps -eo pid,pgid,ppid,comm | grep 进程名,其中-e输出所有进程,-o指定输出列(PID、PGID、PPID、命令)。

1.2 组长进程

  • 组长进程的 PID 等于进程组的 PGID。
  • 作用:可创建进程组或组内进程。
  • 生命周期:从创建到最后一个进程离开为止,与组长是否终止无关(只要组内有进程存在,进程组就存在)。

2. 会话

2.1 什么是会话

  • 会话是一个或多个进程组的集合,有唯一的会话 ID(SID)。
  • 示例:通过管道和后台运行符&创建进程组集合,如proc2 | proc3 &proc4 | proc5 | proc6 &会形成两个进程组,同属一个会话。
  • 查看方式:ps axja显示所有用户进程,x显示无控制终端进程,j显示作业控制相关信息),可观察到同一管道中的进程 PGID 相同。

每次登录成功,系统必须为用户新建一个会话,会话内部必须默认有一个进程组,叫做bash(独立进程,独立进程组)。将该会话的ID设置成为bash进程的pid!

2.2 如何创建会话

  • 调用setsid函数,原型:
    #include <unistd.h>
    pid_t setsid(void); // 成功返回SID,失败返回-1
    
  • 限制:调用进程不能是进程组组长,否则报错。解决方式:先fork创建子进程,父进程终止,子进程执行setsid(子进程继承 PGID 但 PID 不同,不会是组长)。
  • 调用后效果:
    • 调用进程成为新会话的会话首进程(会话中唯一进程)。
    • 调用进程成为进程组组长(新 PGID 为其 PID)。
    • 切断与原控制终端的联系(若存在)。

2.3 会话 ID(SID)

  • 会话首进程的 PID 即为 SID(会话首进程必为进程组组长,故 SID 等价于其 PGID)。

3. 控制终端

  • 定义:用户登录系统后,Shell 进程关联的终端(终端设备或伪终端),由 Shell 启动的进程会继承该控制终端,默认标准输入 / 输出 / 错误指向控制终端。
  • 核心关系:
    • 一个会话最多有一个控制终端,由会话首进程打开。
    • 会话首进程若与控制终端连接,则称为控制进程。
    • 会话中的进程组分为前台进程组(1 个)和后台进程组(多个)。
    • 终端特殊按键信号(Ctrl+CSIGINTCtrl+\SIGQUITCtrl+ZSIGTSTP)仅发送给前台进程组。
    • 终端断开时,挂断信号发送给控制进程(会话首进程)。

4. 作业控制

4.1 作业与作业控制

  • 作业:用户为完成任务启动的进程集合,可包含单个或多个进程(通常通过管道协作)。
  • 作业控制:Shell 通过前后台管理作业(而非单个进程),支持同时运行 1 个前台作业和多个后台作业。

4.2 作业号

  • 后台作业通过&标识,执行后返回作业号(如[1])和进程 PID。
  • 默认作业标识:
    • +:当前默认作业(fg 命令缺省时操作对象)。
    • -:即将成为默认作业(当前默认作业退出后)。
    • 无符号:其他作业。

4.3 作业状态

  • 运行中:后台作业正常执行。
  • 已停止:通过Ctrl+Z挂起(接收SIGTSTP信号)。
  • 完成:作业执行结束。

4.4 作业操作

  • 挂起:前台作业按Ctrl+Z,状态变为 “已停止”。
  • 切回前台fg [作业号],缺省操作默认作业(带+的作业)。
  • 查看作业jobs(显示所有后台 / 挂起作业),-l显示详细信息(含 PID),-p只显示 PID。

5. 守护进程

  • 定义:在后台长期运行的进程,脱离控制终端,独立于用户会话,通常用于提供服务(如服务器进程)。
  • 实现代码(Daemon.hpp)
    #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 = "/";
    const char *dev_null = "/dev/null";void Daemon(bool ischdir, bool isclose)
    {// 1. 忽略异常退出信号signal(SIGCHLD, SIG_IGN); // 忽略子进程退出信号signal(SIGPIPE, SIG_IGN); // 忽略管道破裂信号// 2. 避免成为进程组组长(fork后父进程退出)if (fork() > 0) exit(0);// 3. 创建新会话(成为会话首进程,脱离原终端)setsid();// 4. 可选:切换工作目录到根目录(避免依赖原目录)if (ischdir) chdir(root);// 5. 关闭或重定向标准输入/输出/错误(脱离终端I/O)if (isclose){close(0);close(1);close(2);}else{// 重定向到/dev/null(丢弃I/O)int fd = open(dev_null, O_RDWR);if (fd > 0){dup2(fd, 0); // 标准输入重定向dup2(fd, 1); // 标准输出重定向dup2(fd, 2); // 标准错误重定向close(fd);}}
    }
    

6. 服务守护进程化示例

// 用法:./server port
int main(int argc, char *argv[])
{if (argc != 2){std::cout << "Usage : " << argv[0] << " port" << std::endl;return 0;}uint16_t localport = std::stoi(argv[1]);// 调用守护进程函数,不切换目录,不关闭文件描述符(重定向到/dev/null)Daemon(false, false);// 启动服务器(示例)std::unique_ptr<TcpServer> svr(new TcpServer(localport, HandlerRequest));svr->Loop();return 0;
}
http://www.dtcms.com/a/613311.html

相关文章:

  • el-upload 上传管理与自定义优化实践
  • 开发中的英语积累 P13:Segment、Inclusive、Exclusive、Movement、Arbitrarily、Generic
  • node语法特性详解
  • 2025-11-15 学习记录--Python-LSTM模型定义(PyTorch)
  • PLB-TV 4K+H.265 编码,无广告超流畅
  • Transformer结构完全解读:从Attention到LLM
  • 【ZeroRange WebRTC】REMB(Receiver Estimated Maximum Bitrate)技术深度分析
  • sharding-jdbc 绑定表
  • 郑州网站制作wordpress 密码失败
  • Dify-Token 应用实现
  • webRTC:流程和socket搭建信令服务器
  • PoA 如何把 CodexField 从“创作平台”推向“内容经济网络”
  • 厦门 外贸商城网站建设网站推广哪个好
  • 小米Java开发校园招聘面试题及参考答案
  • 哪个网站做头像比较好网片式防护围栏
  • LangChain Memory 使用示例
  • 【剑斩OFFER】算法的暴力美学——寻找数组的中心下标
  • APIs---Day01
  • 猪只行为状态识别与分类:基于YOLO13-C3k2-ESC模型的实现与优化_3
  • 宁波网站建设方案推广公司网站设计
  • [智能体设计模式] 第10章:模型上下文协议(MCP)
  • 使用docker-composer安装MySQL8、Redis7、minio脚本
  • linux的nginx版本升级
  • 支持selenium的chrome driver更新到142.0.7444.162
  • 【 Java八股文面试 | JVM篇 内存结构、类加载、垃圾回收与性能调优 】
  • 网站开发和前端是一样吗化妆品网站模板
  • Mujoco 机械臂进行 PBVS 基于位置的视觉伺服思路
  • 【玄机靶场】Crypto-常见编码
  • 360加固 APK 脱壳研究:安全工程师视角下的防护与还原原理解析
  • AI面试速记