DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

 

 

  • 原本写完上一篇【并发编程三】C++进程通信(管道pipe),就准备写消息队列的c++demo了,但是真正查找资料才发现网上都是linux下的消息队列的c++demo,就没有windows下的消息队列的进程通信的demo。在查找相关资料的过程中发现了windows下进程和linux下进程的不同点,网上说法也是各说纷纭,在查阅相关资料后,记录下了这篇文章。

一、进程通信(IPC)

进程通信( InterProcess Communication,IPC)就是指进程之间的信息交换。实际上,进程的同步与互斥本质上也是一种进程通信

二、Linux进程通信

1、管道(pipe)

如上一篇博文介绍,管道分为匿名管道和命名管道。他们特点如下

1.1、匿名管道

特点

  • 实现简单。
  • 单项通信,(如果需要双向通信,需要建立两个管道)
  • 有大小限制。
  • 只可以在父子进程间使用。(or同一进程创建的两个子进程间使用)
  • 只能在同一台电脑使用。

缺点

  • 通信⽅式是效率低的,因此管道不适合进程间频繁地交换数据。

1.1、命名管道(有名管道)

特点

  • 实现简单
  • 双向通信。
  • 有大小限制。
  • 可以在不同进程间使用。(没有父子进程的限制)
  • 可以在同一网络的不同电脑上的进程使用。

缺点

  • 通信⽅式是效率低的,因此管道不适合进程间频繁地交换数据。

2、消息队列(message queue)

简介

  • 消息队列是保存在内核中的消息链表,在发送数据时,会分成⼀个⼀个独⽴的数据单元,也就是消息体(数据块),消息体是⽤户⾃定义的数据类型,消息的发送⽅和接收⽅要约定好消息体的数据类型,所以每个消息体都是固定⼤⼩的存储块,不像管道是⽆格式的字节流数据。如果进程从消息队列中读取了消息体,内核就会把这个消息体删除。

缺点
消息这种模型,两个进程之间的通信就像平时发邮件⼀样,你来⼀封,我回⼀封,可以频繁沟通了。
但邮件的通信⽅式存在不⾜的地⽅有两点,

  • ⼀是通信不及时,
  • ⼆是附件也有⼤⼩限制

所以,消息队列不适合⽐较⼤数据的传输,消息队列通信过程中。存在⽤户态与内核态之间的数据拷⻉开销,

3、共享内存(shared memmory)

消息队列的读取和写⼊的过程,都会有发⽣⽤户态与内核态之间的消息拷⻉过程。那共享内存的⽅式,就很好的解决了这⼀问题。

现代操作系统,对于内存管理,采⽤的是虚拟内存技术,也就是每个进程都有⾃⼰独⽴的虚拟内存空间,不同进程的虚拟内存映射到不同的物理内存中。所以,即使进程 A中 和 进程 B中 的虚拟地址是⼀样的,其实访问的是不同的物理内存地址,对于数据的增删查改互不影响。

共享内存的机制,就是拿出⼀块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写⼊的东⻄,另外⼀个进程⻢上就能看到了,都不需要拷⻉来拷⻉去,传来传去,⼤⼤提⾼了进程间通信的速度。

  • 下一篇,我们会讲下具体的代码实现。

4、信号量(Semaphore)

⽤了共享内存通信⽅式,带来新的问题,那就是如果多个进程同时修改同⼀个共享内存,很有可能就冲突了。例如两个进程都同时写⼀个地址,那先写的那个进程会发现内容被别⼈覆盖了。为了防⽌多进程竞争共享资源,⽽造成的数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只能被⼀个进程访问。正好,信号量就实现了这⼀保护机制。

  • 信号量其实是⼀个整型的计数器,主要⽤于实现进程间的互斥与同步,⽽不是⽤于缓存进程间通信的数据。

讲解完共享内存的实现,我们会具体讲下信号量的代码实现。

5、信号(signal)

上⾯说的进程间通信,都是常规状态下的⼯作模式。对于异常情况下的⼯作模式,就需要⽤「信号」的⽅
式来通知进程。

在 Linux 操作系统中, 为了响应各种各样的事件,提供了⼏⼗种信号,分别代表不同的意义。我们可以通过 kill -l 命令,查看所有的信号:

进程在后台运⾏,可以通过 kill 命令的⽅式给进程发送信号,但前提需要知道运⾏中的进程 PID号。(C++可以调用linux下的kill接口。)

6、套接字(socket)

匿名管道、消息队列、共享内存、信号量和信号都是在同⼀台主机上进⾏进程间通信,那要想跨⽹络与不同主机上的进程之间通信,就需要 Socket 通信了。(命名管道也可以实现)

7、动态库(so)

全局数据可以被调用库的所有进程共享,这就又给进程间通信开辟了一条新的途径,当然访问时要注意同步问题。

虽然可以通过DLL进行进程间数据共享,但从数据安全的角度考虑,我们并不提倡这种方法,使用带有访问权限控制的共享内存的方法更好一些。

参考:windows下进程间通信的
参考:进程通信方法(LINUX和WINDOWS下),线程通信方法(LINUX和 WINDOWS下)

三、windows进程通信

1、管道(pipe)

同:linux

2、邮件槽(Mailslots)

Mailslots 提供单向通信。 创建 mailslot 的任何进程都是 mailslot 服务器。 其他进程(称为 mailslot 客户端)通过将邮件写入其 mailslot 来将邮件发送到 mailslot 服务器。 传入邮件始终追加到 mailslot。 mailslot 保存邮件,直到 mailslot 服务器读取邮件。 进程可以是 mailslot 服务器和 mailslot 客户端,因此可以使用多个 mailslot 进行双向通信。

这个用的不多,感兴趣的可以参考官方文档。本人后面不再做邮件槽相关的c++demo.
链接: 进程间通信|Mailslots
链接: Windows——进程间通信

其他

有文章说,linux下的消息队列对应windows下的邮件槽(如Windows与Linux下进程间通信技术比较),但是这个没有官方文档说明,且windows下也有消息队列的定义(如消息和消息队列),但是和linux下的消息队列又不是一个东西,我们就不过多深究了,后续还是做些共享内存和信息量的c++demo。

3、文件映射(file mapping)

将磁盘上的文件映射入内存,所谓映射就是先在内存中分配一块内存预备使用,在使用的时候再将文件加载入内存。
参考:Windows上的文件映射与内存共享
参考:利用邮槽(mailslot)进行应用程序间的通讯实例

5、共享内存(shared memmory)

同:linux

6、信号量(Semaphore)

同:linux

7、信号(signal)

windows没有信号这个概念,但是会提供类似功能的api,比如,杀死进程:linux下的kill信号,windows下提供TerminateProcess的api接口。

8、套接字(socket)

同:linux

9、组件对象模型 (COM)

参考:OPC DA调研报告

 
posted on   DoubleLi  阅读(367)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2014-03-16 source code analyzer 功能强大的C/C++源代码分析软件 Celerity CRACK 破解版
2014-03-16 分析函数调用关系图(call graph)的几种方法
2014-03-16 用CodeViz绘制函数调用关系图(call graph)
2014-03-16 C++的辅助工具介绍
2013-03-16 位运算中的异或运算 .
2013-03-16 按位与、或、异或等运算方法
2012-03-16 Javascript 对象用法
点击右上角即可分享
微信分享提示