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

Linux 进程间通信

目录

1. 目的

2. 管道 

2.1 核心原理 

2.2 匿名管道

2.3 命名管道 

3. System V IPC

3.1 简介

3.2 共享内存(Shared  Memory)

3.3 消息队列 (Message Queues)

3.4 信号量(Semaphores)

3.5 内核结构图(部分)


1. 目的

  · 数据传输:一个进程需要将它的数据发送给另一个进程

  · 资源共享:多个进程之间共享同样的资源

  · 事件通知:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时通知父进程)

  · 进程控制: 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

  本质:让不同的进程,看到同一份资源!

2. 管道 

2.1 核心原理 

  所以,内核文件系统的设计管理本身就可以做到:让不同的进程,看到同一份资源。

  我们把从一个进程连接到另一个进程的一个 数据流 称为一个 “管道”。

2.2 匿名管道

  使用系统接口,基于内核创建管理的一种内核级文件,本质是一个内核缓冲区,进程通过读写这个缓冲区实现通信。

#include <unistd.h>

       int pipe(int pipefd[2]);

  输出型参数:pipefd文件描述符数组:pipefd[0]读端pipefd[1]写端

  成功返回0; 失败返回-1, 错误码被设置 

  只能用于具有 “亲缘关系” 的进程之间,通常用于父子进程,因为子进程继承拷贝了父进程的大部分内核数据结构信息,这其中就 包括所打开的文件信息(fd_arry)。

  四种情况:(命名管道也一样)

  1. 管道内没有数据 && 写端不关闭:读端阻塞等待

  2. 管道内被写满 && 读端不关闭 : 写端阻塞等待

  3. 写端关闭,读端可以继续读取管道内的数据,直到读完

  4. 读端关闭 && 写端尝试写入,OS发送异常信号(13)直接终止写端进程 

  五种特性:

  1. 用于具有亲缘关系的进程间

  2. 单向性 (命名管道同)

  3. 面向字节流(命名管道同)

  4. 自带同步机制(即上述的 “四种情况”)(命名管道同)

  5. 生命周期随进程,临时性 

  补充:默认管道大小通常是64KB,系统全局最大管道大小可以通过 /proc/sys/pipe-max-size 进行调整;也可以在创建管道后,使用 fcntl 系统调用动态调整管道的大小。

  为什么要有大小限制?

        首先是 为了避免资源耗尽,若不限制管道的大小,多个进程可能消耗大量内存,导致系统不稳定 。

        其次是 为了平衡速度与内存:适当的管道大小可以在速度和内存占用之间找到平衡。

  所以,设置合适的管道大小,有助于提高进程间的通信效率,避免不必要的阻塞。

  相关的测试代码获取可点击:前往我的代码仓库! 

2.3 命名管道 

  磁盘级文件,但是不能持久化存储数据。

  它可以让没有 “亲缘关系” 的进程间也能通信 。

  创建:

  1. 系统的指令工具:mkfifo

  2. C 库函数:

#include <sys/types.h>
#include <sys/stat.h>

       int mkfifo(const char *pathname, mode_t mode);

  成功返回0; 失败返回-1, 错误码被设置。

  在操作上,和 匿名管道不同的是:命名管道的打开规则(open) 

  通常,如果不设置 O_NONBLOCK 参数: 

  写端先启动,阻塞等待 直到有写端打开时才同步打开此管道

  读端先启动读端进程阻塞,等待写端进程打开管道;此时启动写端进程,由于读端已经阻塞,导致写端进程也卡住,等待读端准备好读取数据 —— 这是典型的 死锁 情况:读写端互相等待,导致两个进程都无法继续执行

  解决方式:1. 写端先open

                    2. 设置非阻塞参数: O_NONBLOCK

                    3. 设置管道超时机制

                    ...... 

   相关代码测试获取可点击:前往我的仓库!

3. System V IPC

3.1 简介

  用于在不同进程之间交换数据 或 同步 的机制!

  同步异步是计算机科学和编程中的常见概念,主要用于描述 任务执行的方式以及程序流控制

  同步(Synchronous): 【阻塞式执行】任务按照顺序执行,一个任务必须等待前一个任务完成后才能继续,确保多个进程访问共享资源 的原子性操作【某个操作,只有两种状态,要么还没开始,要么已经结束】防止资源竞争和数据冲突

  异步(Asynchronous): 任务可以并行或非阻塞执行,不需要等待前一个任务完成;提高效率,减少等待时间,但是代码复杂度增加,难以调试和控制程序流 。

  场景:

  同步:文件读写,小型脚本,CLI命令,...

  异步:网络请求,GUI事件处理,服务器处理多用户请求,...

  在实际开发中,同步和异步通常结合使用,根据具体的场景才能选择合适的方案。

  回到正题:

  System V IPC 是一套独立于文件系统的通信机制,通过内核维护IPC对象资源在进程间进行通信,所以,即使进程终止,IPC对象仍然可以保留在内核中,直到显示删除;它在一定程度上,避免了传统文件系统操作带来的性能开销,适合高效的进程间数据交换和同步。

  它包括:共享内存,消息队列,信号量

  接下来,以共享内存为重点讲解,其它次之来分别介绍

3.2 共享内存(Shared  Memory)

  基于内存段,直接映射到进程的地址空间,数据在内存中传递(双向,可读可写),减少了内核态与用户态切换以及数据拷贝,速度快,传输量大 

  操作:

  1. 创建/获取

  2. 映射到进程的地址空间/解除映射

  3. 控制

  相关代码测试获取可点击:前往我的仓库! 

3.3 消息队列 (Message Queues)

   允许一个进程以结构化消息的形式向队列发送消息,另一个进程向队列中读取消息;消息有优先级,可以按照特定顺序读取

  操作是类似的(注意对比): 

 

3.4 信号量(Semaphores)

  主要用于进程间的 同步【具有一定的顺序性】和 互斥【对共享资源的独占访问】,确保进程在访问共享资源时的协调和安全性;并不作为一种朴素的数据通信。

  我们把 共享资源 就称为 : 临界资源 或 互斥资源

  涉及到访问临界资源的程序代码就叫:临界区 

  信号量的本质就是:一个描述管理互斥资源的 “计数器”

  下面引入一个具体的场景进行类比理解:

  用户态接口: 

  (注意对比)

3.5 内核结构图(部分)

   本篇分享到此结束,如果对你有所帮助,就是对小编最大的鼓励,可以的话,点赞,收藏并分享给您的小伙伴一起学习吧!

  关注小编,持续更新中......

相关文章:

  • 【QT】-易错点笔记-2025-2-7
  • 【组件安装FAQ】Connector 24.10.06-1: [cnc0306002] already exists.
  • 实现自定义圆角imageView, 抗锯齿
  • Django 模型的逆向工程
  • VMware Workstation安装rocky9.5虚拟机
  • 操作系统 2.2-多进程总体实现
  • P8255 [NOI Online 2022 入门组] 数学游戏 题解
  • C++:模板(上篇)
  • 【C++】析构函数与虚析构函数区别
  • 【Proteus仿真】【STM32单片机】智能阳台控制系统
  • 利用PHP爬虫根据关键词获取17网(17zwd)商品列表:实战指南
  • 【记录】高性能服务器运行DeepSeek
  • JavaScript(最后一个元素的索引就是数组的长度减 1)array.length - 1
  • 清华北大推出的 DeepSeek 教程(附 PDF 下载链接)
  • [傻瓜式教学]如何将MathType公式编辑器内嵌到WPS工具栏中
  • 刘火良 FreeRTOS内核实现与应用之1——列表学习
  • langchain系列(九)- LangGraph 子图详解
  • 从零开始实现大语言模型(十三):预训练大语言模型GPTModel
  • VUE_自定义指令,全局指令注册
  • LBE大空间文档
  • 学生成绩管理系统网站建设/网络企业推广
  • 沂源放心企业网站建设方案报价/软件推广的渠道是哪里找的
  • 宠物网站建设规划书/企业网站的类型
  • 学校网站怎么做的好处/怎么学seo基础
  • 外管局网站做延期收汇报告/百度推广代理
  • 如何做中介网站/网站首页制作网站