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

进程管理和IPC

1.进程管理

1.fork作用

fork() 是 Unix/Linux 系统中最核心的系统调用之一,其核心作用是创建一个与当前进程(父进程)几乎完全相同的新进程(子进程),从而实现进程的 “复制式” 并发。
具体作用可从以下几个维度理解:

1.进程复制:创建 “镜像” 子进程
fork() 会生成一个新的子进程,子进程会复制父进程的大部分资源,包括:

代码段(执行的程序指令)、数据段(全局变量、静态变量)、堆、栈(函数调用栈、局部变量);
文件描述符表(打开的文件、管道、网络套接字等);
进程状态(如信号掩码、工作目录、环境变量等)。

现代系统通过 “写时复制(COW,Copy-On-Write)” 优化这一过程:初始时子进程并不实际复制内存,而是与父进程共享内存页;仅当子进程或父进程修改内存数据时,才会触发真正的内存复制(避免不必要的资源浪费)。

2.执行分流:父子进程独立运行
子进程创建后,会从 fork() 系统调用的下一条指令开始独立执行(而非从程序开头重新运行)。
通过 fork() 的返回值,父子进程可以区分自身身份并执行不同逻辑:

父进程中,fork() 返回子进程的 PID(进程 ID,正整数);
子进程中,fork() 返回 0;
若创建失败(如系统进程数达上限),返回 -1。

2.vfork作用

vfork() 是 Unix/Linux 系统中用于创建子进程的系统调用,其设计初衷是为 “子进程创建后立即执行新程序(通过 exec 族函数)” 的场景提供极致高效的进程创建方式,核心作用是通过 “共享资源 + 阻塞父进程” 的机制,减少子进程创建到程序替换期间的资源开销。
具体作用与特性:
1.高效创建子进程(核心目标)
vfork() 的设计源于早期 Unix 系统中 fork() 的性能缺陷:早期 fork() 会完整复制父进程的地址空间(代码段、数据段、堆、栈等),而如果子进程创建后立即调用 exec 族函数(用新程序替换自身),这种复制会成为 “无效开销”(复制的内存马上被新程序覆盖)。

vfork() 通过完全共享父进程的地址空间(不复制内存),避免了这种无效开销,让子进程创建的时间和内存成本极低。

2.强制父进程阻塞(确保资源安全)
为了防止共享地址空间导致的冲突(父进程和子进程同时修改内存),vfork() 会强制父进程进入阻塞状态,直到子进程执行以下操作之一:

调用 exec 族函数(加载新程序,替换共享的地址空间,此时父子进程资源自然分离);
调用 exit(子进程终止,释放共享资源)。

这种机制保证了子进程在使用共享资源期间,父进程不会干扰,避免内存数据混乱。

3.限定子进程行为(安全约束)
由于子进程与父进程共享地址空间,vfork() 对其子进程的行为有严格隐性约束:

子进程不能修改共享内存(如全局变量、堆数据),否则会直接破坏父进程的数据;
子进程不能从函数中返回(会导致父进程的栈被破坏),必须通过 exec 或 exit 结束。
适用场景(已逐步被淘汰)
vfork() 仅适用于子进程创建后立即调用 exec 族函数的场景(如早期 shell 执行命令时,创建子进程加载新命令程序)。

3.exec 族函数

exec 族函数的作用是用新程序替换当前进程的代码段、数据段、堆、栈(进程 ID 不变),常用于子进程创建后执行与父进程完全不同的程序。

4.子进程回收:wait 与 waitpid(避免僵尸进程)

僵尸进程仅占用内核中进程表项的少量空间(存储 PID、退出状态等元数据),不占用用户态内存或其他资源。其主要危害是大量积累时会耗尽进程表项,导致新进程无法创建。解决方式是确保父进程及时调用 wait()/waitpid() 回收子进程,或通过信号机制(如 SIGCHLD)处理子进程终止事件。

1.wait():阻塞等待任意子进程终止

2.waitpid():更灵活的子进程回收
wait 是 waitpid 的简化版,waitpid 支持指定等待的子进程、非阻塞等待等高级功能。

子进程退出与父进程的关系:若父进程先于子进程退出,子进程会被 init 进程(PID=1,或 systemd 等)收养,最终由 init 回收,避免成为 “孤儿僵尸进程”。

5.进程退出:exit 与 _exit 的核心差异

维度 exit(status)(库函数) _exit(status)(系统调用)
函数类型 C 标准库函数(封装了系统调用) 直接的系统调用(内核级接口)
核心行为 先执行用户态清理,再终止进程 直接终止进程,不执行用户态清理
标准 I/O 缓冲区 会刷新所有打开的标准 I/O 流(如 printf 缓冲区) 不刷新用户态缓冲区(仅内核缓冲区可能被刷新)
清理函数 执行 atexit/on_exit 注册的用户清理函数 不执行任何用户注册的清理函数
适用场景 正常退出用户程序,需确保资源完整释放 子进程退出(避免与父进程缓冲区冲突)或快速强制退出

exit 和 _exit 的核心差异在于是否执行用户态清理逻辑(清理函数 + 缓冲区刷新)。理解这一点的关键是:exit 是 “优雅退出”,确保用户态资源完整处理;_exit 是 “直接退出”,跳过用户态处理,仅内核级终止。在子进程中,优先使用 _exit 可避免与父进程的资源冲突。

进程分配的资源都会释放。进程在用户空间分配的内存(代码段、数据段、堆、栈)、打开的文件描述符(用户态视角的 FD 表项)等。

2.IPC

1.管道

管道是最基础的 IPC 机制,本质是内核维护的一个单向字节流缓冲区,适用于数据流式传递。

1.匿名管道(Anonymous Pipe)

特点:
仅用于亲缘进程(如父子、兄弟进程),通过 fork 继承文件描述符;
半双工(单向通信),需创建两个管道实现双向通信;
数据读完后自动删除,不持久化。

2.命名管道(Named Pipe/FIFO)

特点:
可用于非亲缘进程(通过文件系统路径标识);
半双工,数据传递方式与匿名管道一致;
以特殊文件形式存在于文件系统(mkfifo 创建),但不占用磁盘空间(数据在内存中)。

2.信号(Signals):异步事件通知

信号是操作系统向进程发送的异步事件通知(如中断、错误),用于简单的事件触发(不适合传递大量数据)。不支持自定义信号。

常见信号:
SIGINT(2):Ctrl+C 触发,默认终止进程;
SIGCHLD(17):子进程退出时,内核向父进程发送;
SIGKILL(9):强制终止进程(无法被捕获或忽略);
SIGSEGV(11):段错误(非法内存访问)。

核心操作:

发送信号:kill(pid, sig)(向指定进程发信号)、raise(sig)(向自身发信号);
处理信号:signal(sig, handler) 或 sigaction(sig, &act, NULL)(注册信号处理函数)。

新信号的处理规则
根据新信号是否被屏蔽,以及信号类型(标准 / 实时),处理逻辑不同:
1.新信号被屏蔽(包含两种情况)
情况 1:新信号是当前正在处理的信号(如处理 SIGINT 时又收到 SIGINT):
内核会暂存该信号(实时信号)或直接丢弃(标准信号),不会打断当前处理函数。
标准信号(1-31 号):不支持排队,多次发送同一信号会被合并,仅在屏蔽解除后处理一次;
实时信号(34-64 号):支持排队,多次发送会按顺序保存,屏蔽解除后依次处理。
情况 2:新信号被主动加入屏蔽集(通过 sigaction 的 sa_mask):
开发者可通过 sigaction 的 sa_mask 字段,在处理信号时主动屏蔽其他信号(避免嵌套处理)。例如,处理 SIGUSR1 时,可在 sa_mask 中加入 SIGUSR2,此时收到 SIGUSR2 会被暂存 / 排队,直到 SIGUSR1 处理完毕。

2.新信号未被屏蔽
若新信号不在屏蔽集中,内核会暂停当前的信号处理函数,先执行新信号的处理函数,执行完毕后再返回继续处理原信号。

这种 “嵌套处理” 可能导致逻辑混乱(如资源竞争),因此实际开发中通常会通过 sa_mask 屏蔽可能干扰的信号。

3.消息队列(Message Queues):带类型的消息传递

消息带类型:每条消息包含一个整数类型(long mtype),接收方可以指定类型读取(如只接收类型为 1 的消息)。

异步通信:发送方发送消息后无需等待接收方处理,可立即返回;接收方可在需要时读取消息。

数据暂存:消息由内核保存,进程退出后消息不会丢失(除非显式删除),直到被读取或队列被删除。

有限制:单条消息大小(通常上限为 8KB)和队列总大小受内核参数限制(可通过 /proc/sys/kernel/msgmax 等配置)。

4.共享内存(Shared Memory):高效数据共享

共享内存(Shared Memory)是效率最高的进程间通信(IPC)机制,其核心原理是让多个进程直接访问同一块内核管理的内存区域,避免了数据在用户态与内核态之间的拷贝(如管道、消息队列的数据传递都需要内核中转),因此特别适合高频、大量数据的交换场景(如视频处理、实时数据共享)。

一、核心特性
高效性:进程直接读写内存,无需内核中转,数据传输效率接近内存访问速度(远高于管道、消息队列)。

共享性:一块共享内存可映射到多个进程的地址空间,进程间数据实时可见。

无数据结构限制:内存内容由用户进程自主定义(可存储结构体、数组等任意数据),灵活度高。

需同步机制:内核不提供数据访问控制,多个进程同时读写可能导致数据混乱,需配合信号量、互斥锁等同步工具。

生命周期:由内核管理,进程退出后内存不会自动释放,需显式删除(否则重启前一直存在于内核中)。

5.信号量(Semaphores):同步与互斥

信号量(Semaphores)是一种用于进程 / 线程同步与互斥的内核级工具,本质是一个受保护的整数计数器,通过原子操作(不可中断的操作)控制对共享资源的访问。其核心作用是:

互斥(Mutual Exclusion):保证同一时间只有一个进程 / 线程访问共享资源(如共享内存、文件);
同步(Synchronization):协调多个进程 / 线程的执行顺序(如 “生产者 - 消费者” 模型中,确保生产者先生产,消费者后消费)。

P 操作 (sem_wait)请求资源:尝试获取资源使用权 若计数器 > 0:计数器 - 1,继续执行;
若计数器 = 0:阻塞等待,直到计数器 > 0。

V 操作 (sem_post)释放资源:归还资源使用权 计数器 + 1;若有进程阻塞等待,唤醒其中一个。

6.套接字(Sockets):跨网络 / 本地通信

3.其他

•核心内容:
c.线程创建与管理:pthread 库(pthread_create/pthread_join/pthread_exit)、线程属性(分离态 PTHREAD_CREATE_DETACHED);
d.线程同步与互斥:
▪互斥锁:pthread_mutex_t(初始化、加锁 / 解锁、销毁,避免死锁的原则:按序加锁、限时锁 pthread_mutex_trylock);
▪条件变量:pthread_cond_t(配合互斥锁实现 “等待 - 唤醒”,解决 “忙等” 问题,如生产者 - 消费者模型);
▪信号量(线程级):sem_t(轻量级同步,可替代互斥锁 + 条件变量的组合场景);
e.线程安全:全局变量 / 静态变量的保护、可重入函数(如 strtok_r 替代 strtok)。
•实践验证:实现一个 “线程池”(固定数量线程处理任务队列,练线程同步与任务调度)。

模块 4:文件 I/O 与 I/O 多路复用(高并发基础)
•核心内容:
i.基础文件 I/O:open/read/write/close(区别于标准 I/O 的 fopen/fread,无缓冲,直接调用系统调用)、文件描述符(FD)管理(dup/dup2 重定向,如标准输出重定向到文件);
j.特殊文件 I/O:设备文件(字符设备 / 块设备)、管道(匿名管道用于父子进程,命名管道用于无亲缘关系进程)、套接字(Socket,网络 I/O 基础);
k.I/O 多路复用:解决 “单线程处理多 FD” 的问题,对比掌握 ——
▪select:FD 数量限制(默认 1024)、效率随 FD 增多下降;
▪poll:无 FD 数量限制,但仍需遍历所有 FD;
▪epoll(Linux 特有):事件驱动、高效(只处理就绪 FD),掌握 epoll_create/epoll_ctl/epoll_wait 及两种触发模式(LT/ET)。
•实践验证:用 epoll 实现一个并发 echo 服务器(支持多个客户端同时连接并回复消息)。

http://www.dtcms.com/a/366015.html

相关文章:

  • 常用假设检验方法及 Python 实现
  • 多层环境室内定位系统综述总结
  • 【JavaEE】(22) Spring 事务
  • 苏哒智能会议一体机:让会议管理进入智能时代
  • Java与Vue构建的企业设备资产管理系统,集成后台管理与移动端操作,覆盖设备全生命周期,支持采购、维护、报废等流程,提供完整源码,助力企业高效管控资产
  • 刻意练习实践说明使用手册
  • nginx配置讲解
  • GitLens:VS Code下高效解决代码追溯的Git管理实用插件
  • Spring Boot + Nacos 配置中心示例工程
  • ego(2)---初始轨迹生成后的关键点采样
  • 一文读懂线性回归的灵魂:成本函数 J(w,b) 全解析
  • K8s基于节点软亲和的高 CPU Pod 扩容与优先调度方案
  • 华为OD最新机试真题-二进制差异数-OD统一考试(C卷)
  • 《K8s网络策略与CNI插件交互问题分析:基于真实案例的排查方法》
  • 卷积操作原来分3种
  • (二)文件管理-基础命令-mkdir命令的使用
  • C++CSP-J/S必背模板
  • Estimating the Number of Sources: An Efficient Maximization Approach
  • 上下文记忆力媲美Genie3,且问世更早:港大和可灵提出场景一致的交互式视频世界模型!
  • Guidelines for using Adaptive Platform interfaces
  • redisson功能完整指南
  • 【OpenGL】LearnOpenGL学习笔记19 - 几何着色器 Geometry Shader
  • 【机器学习深度学习】RAG边界处理策略
  • Vision Pro图像处理工具全解析
  • ClickHouse使用Docker部署
  • 刷新记录:TapData Oracle 日志同步性能达 80K TPS,重塑实时同步新标准
  • mysy2使用
  • Windows 开发环境这么难配,为什么还有那么多人在用?
  • Axure文件上传高保真交互原型:实现Web端真实上传体验
  • 机器能否真正语言?人工智能NLP面临的“理解鸿沟与突破