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

进程通信的学习

共享内存(Shared Memory)—— 像共用一个黑板

初始化时需要内核介入,但后续通信可直接在用户态完成​​:

  • 🧾 比喻:两个房间共享一个“黑板”,你写,我读,大家都能看到。

  • 优点:传输速度快,因为不用来回搬数据(就在内存里)。

  • 缺点:需要加锁,不然容易“写错乱”,像两个人同时擦黑板、写字,会打架。

使用场景:数据量大、频繁交流的进程之间通信,比如视频播放、数据处理等。

1. 基于数据结构的共享(结构化共享)

​定义​​:进程之间通过​​预定义的数据结构​​(如消息格式、协议、类/对象等)交换数据,双方必须严格遵守这种结构才能正确解析数据。

​通俗比喻​​:
假设两个人要交换包裹,他们必须提前约定好包裹的格式,比如:

  • ​包裹必须用红色箱子装​​;

  • ​第一层放书,第二层放衣服,第三层放零食​​;

  • ​箱子外必须贴标签标明内容​​。

双方严格按照这个格式打包和拆包,即使他们不面对面交接(比如通过快递),也能准确理解对方传递的信息。

​技术场景​​​​:​

  • ​消息队列(Message Queue)​​:发送方和接收方约定消息的字段(如 {type: "order", data: "..."})。

  • ​RPC(远程过程调用)​​:调用远程函数时,参数和返回值需要序列化成结构化的数据(如JSON、Protobuf)。

  • ​网络协议(HTTP、TCP包头)​​:数据包必须包含协议规定的头部和字段。

​特点​​:

  • ​强约束​​:数据必须按固定格式组织,灵活性低,但可靠性高。

  • ​跨语言/跨平台​​:适合不同语言或系统间的通信(比如Java程序向Python程序发JSON数据)。

  • ​需要编解码​​:数据可能需要序列化(编码)和反序列化(解码)。


​2. 基于存储区的共享(原始内存共享)​

​定义​​:进程直接读写​​同一块物理内存区域​​,数据以原始二进制形式存在,没有预定义的结构,进程自行决定如何解释这些数据。

​通俗比喻​​:
两个画家共用一块白板作画,白板本身没有分区或格式限制:

  • 画家A在白板左边画了一只猫;

  • 画家B看到后,直接在右边补了一条鱼;

  • 两人需要​​协调作画时间​​(比如用信号量),否则可能同时修改同一区域,导致画面混乱。

​技术场景​​:

  • ​共享内存(Shared Memory)​​:多个进程访问同一块内存区域,直接读写二进制数据。

  • ​内存映射文件(Memory-Mapped File)​​:文件内容映射到内存,进程直接操作内存来修改文件。

​特点​​:

  • ​高效​​:无需数据复制或编解码,直接操作内存,速度极快。

  • ​无结构​​:数据是“原始”的,进程自行定义如何解析(比如前4字节是整数,后100字节是字符串)。

  • ​需同步​​:必须用锁、信号量等机制避免数据竞争(如两个进程同时修改同一地址)。

  • ​依赖系统​​:通常仅限同一台机器的进程使用。

消息队列(Message Queue)—— 像留言板或邮箱

  • 📮 比喻:像在公共区域放一个“邮箱”,一个人投递信息,另一个人来读取。

  • 优点:不需要亲戚关系,任何进程都可以通过这个邮箱沟通。

  • 缺点:复杂度比管道略高,而且消息数量和大小有限制。

使用场景:多个程序之间解耦、协作,例如生产者-消费者模型。

消息队列(Message Queue)—— 快递柜​

通信都需要用户态到内核态的切换​​,由内核直接管理通信过程:​

📦 ​​类比场景​​:

你和同事通过公司楼下的 ​​公共快递柜​​ 传递文件:

  • ​独立存储​​:每个文件被包装成独立包裹(消息),带类型标签。

  • ​异步处理​​:你放包裹后不用等同事,对方有空时凭类型标签取件。

  • ​持久性​​:快递柜断电后包裹还在(部分消息队列支持持久化)。

​计算机中的消息队列​​:

  • 内核维护的链表结构,进程通过 msgget()msgsnd()msgrcv() 操作。

  • 适合多对多通信,且允许非实时处理(如日志收集)。

1. 直接通信方式(点名道姓)​

​定义​​:进程在通信时​​必须明确指定对方的标识​​(如进程ID、名称或地址),类似打电话需要知道对方的号码。

​通俗比喻​​:

  • 想象你和朋友约饭,直接发微信给他:“​​张三​​,今晚6点老地方见!”

  • ​必须明确对方是谁​​,且双方需“在线”(如进程必须存在且准备好通信)。

​技术场景​​:

  • ​管道(Pipe)​​:父进程和子进程通过管道直接通信。

  • ​Socket直连​​:客户端直接指定服务器IP和端口发送请求。

  • ​信号(Signal)​​:进程A向进程B发送SIGTERM终止信号(需知道B的PID)。

​特点​​:

  • ​强耦合​​:通信双方依赖彼此的身份(如进程ID),一方退出可能导致通信失败。

  • ​点对点​​:通常是一对一通信。

  • ​实时性​​:要求双方同时存在(类似打电话需要对方接听)。


​2. 间接通信方式(匿名投递)​

​定义​​:进程通过​​中间媒介​​(如消息队列、共享内存或文件)通信,无需知道对方是谁,类似把信投到邮筒,邮局负责传递。

​通俗比喻​​:

  • 你在公司群里发消息:“今晚6点聚餐,想来的接龙!”

  • ​无需指定具体接收者​​,感兴趣的人自行查看消息。

  • 即使你发消息时有人不在线,他们之后也能看到(异步通信)。

​技术场景​​:

  • ​消息队列(Message Queue)​​:进程A向队列发送消息,进程B从队列读取。

  • ​共享内存(Shared Memory)​​:多个进程读写同一块内存区域。

  • ​文件​​:进程A写入文件,进程B稍后读取。

  • ​发布-订阅模型​​:进程向主题(Topic)发布消息,订阅该主题的进程接收。

​特点​​:

  • ​解耦​​:发送方和接收方无需知道彼此存在(通过中间媒介隔离)。

  • ​灵活性​​:支持一对多、多对多通信(如多个生产者向队列发消息,多个消费者读取)。

  • ​异步性​​:接收方可以延迟处理消息(如消息队列堆积)。

共享存储和间接存储的区别

🌟 一、共享存储(Shared Storage)

✅ 通俗理解:

就像你和朋友一起用一个笔记本(共享内存),你写一段话,他马上能看到,速度快、效率高。

📌 特点:

  • 数据在共享内存区中,多个进程可读可写

  • 速度快(不需要数据复制)

  • 需要自己处理同步问题(比如防止你们两个同时写进而“打架”)

📚 举例:

  • 共享内存(Shared Memory)

  • 内存映射文件(mmap)


🌟 二、间接存储(Indirect Storage)

✅ 通俗理解:

像你写了纸条交给老师(操作系统),老师再交给你的同学。你们之间不直接接触数据,而是通过“中间媒介”。

📌 特点:

  • 通信通过系统提供的中间机制完成(比如消息队列)

  • 进程之间看不到彼此的内存

  • 安全性好,但速度比共享慢一些

📚 举例:

  • 消息队列(Message Queue)

  • 管道(Pipe)

  • 套接字(Socket)

 管道(Pipe)—— 单向水管​

🚰 ​​类比场景​​:

想象你和朋友用一根 ​​只能单向流水​​ 的水管传递纸条:

  • ​单向性​​:纸条只能从你这一端塞进去,朋友从另一端取出。

  • ​血缘限制​​:这根水管只能在你和亲兄弟姐妹(父子进程)之间用。

  • ​容量限制​​:水管一次只能传少量纸条,满了会堵住,空了会等待。

​计算机中的管道​​:

  • 本质是内核中的一段缓冲区,通过 pipe() 系统调用创建。

  • 适合简单场景,比如在命令行中用 ls | grep "txt" 将 ls 的结果传给 grep

管道通信(Pipe)—— 像传纸条

  • 📝 比喻:两个房间之间开了一个“投纸条的通道”,一个人写纸条塞进去,另一个人接着看。

  • 优点:简单,适合父子进程(比如一个程序启动另一个程序)。

  • 缺点:只能一个方向传纸条(单向管道),而且只能用于有亲戚关系的进程。

使用场景:父进程和子进程传输数据,比如 ls | grep 这样的命令管道。

管道通信和共享存储的区别

一句话总结:

  • 管道通信:像“传纸条”,一人写、一人读,有顺序、速度适中。

  • 共享存储:像“共用一个黑板”,大家可以自由写写画画,速度快但容易冲突。


🌟 一、管道通信(Pipe)

✅ 通俗理解:

想象你和朋友在隔壁房间,中间有个小洞,你写了张纸条塞过去,他收到并阅读。这就是“管道”——

  • 一边写,一边读

  • 数据一旦读了,就没了(像传过去的纸条看完就丢了)

📌 特点:

  • 单向(或双向)传递数据

  • 读写有顺序,像排队

  • 数据传完就清空(不可回头看)

  • 一般用于父子进程之间的通信


🌟 二、共享存储(Shared Memory)

✅ 通俗理解:

你和朋友共用一块黑板,你写在左边,他读右边,中间没人挡。大家都能随时访问黑板上的内容。

  • 数据就在那里,随时写,随时看

  • 你写的内容不会消失(除非擦掉)

📌 特点:

  • 速度快(因为直接访问内存)

  • 可以大容量传数据

  • 但要小心写冲突,需要“加锁”来避免打架

总结

相关文章:

  • 多值字典表设计:优雅处理一对多关系的数据库方案
  • C++基础精讲-01
  • Ubuntu环境下,EDK2+EmulatorPkg编译运行UEFI固件
  • Ollama教程与大模型本地部署指南
  • 32 python json
  • PostgreSQLs数据库考试
  • MySQL 中的聚簇索引和非聚簇索引有什么区别?
  • Redis的过期和内存淘汰策略
  • 新技术学习方法
  • 卷积神经网络 CNN 系列总结(一)---基础知识点
  • ubuntu22.04 安装-ODBC驱动-SQLserver
  • vue中根据html动态渲染内容2.0
  • 无人设备遥控器之数据分析与处理篇
  • 一周学会Pandas2 Python数据处理与分析-Pandas2数据读取
  • ------------------V2024-2信息收集完结------------------
  • Linux 入门五:Makefile—— 从手动编译到工程自动化的蜕变
  • 使用开源项目蜂信物联/FastBee前端安装失败
  • Python进阶编程总结
  • vue项目proxy代理的方式
  • DeepSeek与搜索引擎:AI生成内容如何突破“语义天花板”
  • 二次开发培训/网站关键词排名seo
  • 网站建设顾问/软文写作发布
  • 专业婚纱摄影网站制作/做整站优化
  • 南昌制作网站软件/推销产品怎么推广
  • 个人网站的制作步骤/成人本科报考官网
  • 中山网站备案/怎么开通百度推广账号