操作系统-进程间的四种通信(共享内存、消息队列、信号、管道)

本文主要是介绍操作系统-进程间的四种通信(共享内存、消息队列、信号、管道),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

进程间通信

文章目录

  • 进程间通信
    • 共享内存
    • 消息队列
    • 信号
      • 信号的接收处理
      • 内核对于信号的基本处理办法
    • 管道通信
      • 无名管道
      • 有名管道

进程间的通信有三种基本的模型,共享内存和消息传递和管道。

  • 共享内存模型会建立起一块协作进程的共享的内存区域,进程通过向共享区域读入或写入数据来交换信息
  • 消息传递模型通过在协作进程间交换信息来实现通信

共享内存

共享内存区是最快的(进程间通信)IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

注意:共享内存没有进行同步与互斥!共享内存不会自动销毁,要手动销毁。

共享内存的原理图 --学习进程前先学习一下内存管理效果感觉更好 -内存管理部分我以己经学完,所以理解的比较轻松,内存管理部分后边我也会在学习一遍,也会有笔记发布在我的博客上。

在这里插入图片描述

了解关于共享内存的接口以及示例可访问下面链接:
https://blog.csdn.net/2202_75305885/article/details/136240275

采用共享内存进行进程间通信,需要通信进程简建立共享内存区域

通常,一片共享内存区域驻留在创建共享内存的进程地址空间内,其他希望使用这个共享内存段的进行通信的进程应将其附加到自己的地址空间。

通常操作系统会试图阻止一个进程访问另一个进程的内存,共享内存需要两个或更多的进程同意取消这一限制。

他们希望通过共享区域内读出或者写入来交换信息,数据的类型或者位置取决于这些进程,而不是受控于操作系统。另外通信的进程需要确保,他们不会向同一位置写入数(可以用同步与互斥来确保)

消息队列

消息队列是有操作系统维护的以字节序列为基本单位的间接通信机制

  • 每个消息是一个字节序列
  • 相同标识的消息组成按先进先出的顺序组成一个消息队列

在这里插入图片描述

消息队列的系统调用

在这里插入图片描述

信号

软中断信号(signal,简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。

进程间的软件中断通知和处理机制,如SIGKILL,SIGSTOP、SIGSTOP等

  • 操作系统在编译你的程序的时候,会缺省的加上对于这些信号的处理例程。

信号的接收处理

  • 捕获(catch):执行进程指定的信号处理函数被调用
  • 忽略(Ignore):执行操作系统指定的缺省处理。
    • 例如:进程终止、进程挂起等
  • 屏蔽(Mask):禁止进程接受和处理信号

缺点:

传送的信息量小,只有一个信号类型

信号的实现

在这里插入图片描述

内核对于信号的基本处理办法

  • Linux内核给一个进程发送信号的方法是,在进程所在的进程表项的信号域设置对应于该信号地位,

  • 内核处理一个进程收到的信号的时机是在一个进程从内核态返回用户态时。所以,当一个进程在内核态下运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理。进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号。

  • 内核处理一个进程收到的软中断信号是在该进程的上下文中,因此,进程必须处于运行状态

  • 如果进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行用户定义的函数。而且执行用户定义的函数的方法很巧妙,内核是在用户栈上创建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程从内核返回弹出栈顶时就返回到用户定义的函数处,从函数返回再弹出栈顶时, 才返回原先进入内核的地方。这样做的原因是用户定义的处理函数不能且不允许在内核态下执行(如果用户定义的函数在内核态下运行的话,用户就可以获得任何权限)。

此处内容摘自 https://baike.baidu.com/item/%E4%BF%A1%E5%8F%B7/7927794?fr=ge_ala 只是摘录部分,全部内容可前往链接

管道通信

进程间基于内存文件的通信机制

  • 也就是说,如果两个进程要使用管道通信,内核会在内存中创建一块内存,只要多个进程能访问到这块内存就可以了
  • 管道其实就是操作系统内核中的一块缓冲区
  • 一次只允许一个进程使用的资源,称为临界资源。管道在同一时刻只允许一个进程对其进行写入或是读取操作,因此管道也就是一种临界资源。而临界资源需要保护,内核也管道文件提供了同步和互斥的功能

无名管道

  • 只能用于具有亲缘关系的进程,像父子进程、兄弟进程、祖孙进程、叔侄进程。其中,指令中的竖线,ps aux | grep,是兄弟关系,因为ps和grep的父进程都是bash。。
  • 半双工,在需要双方进行通信的时候,需要建立起两个管道。
  • **进程退出,管道释放。这里的进程是指持有管道的最后一个进程。**当然,你也可以选择将所有进程手动关闭掉那两个文件描述符。
  • 内核会对管道(匿名/命名管道)进行同步与互斥。- 无名管道的大小一般是64K
  • 无名管道默认是阻塞模式

在这里插入图片描述

无名管道只能在血缘的进程间通信的原因

无名管道通信指的是多个进程在内核申请的管道文件进行通信,这就需要所有进程能够知道这个申请成功管道文件的读写文件描述符,有亲缘关系的进程可以在分离进程之前在内核空间申请管道文件,在分离进程后所有有亲缘关系的进程都能通过复制的文件描述符访问同系统文件表,进而访问一个管道文件的地址,因此无名管道只适用于有亲缘的进程之间的通信

有名管道

在内核中这块缓冲区是有标识的,意味着所有的进程都可以通过这个标识找到这块缓冲区进行通信,也就是命名管道可以用于同一主机上的任意进程进行通信。
命名管道的标识实际上是一个文件,可见于文件系统,意味着所有进程都可以通过打开文件进而访问到内核中的缓冲区。

特性:

  • 半双工
  • 面向字节流,读写非常灵活
  • 有名管道在文件系统中具有唯一的路径名,可以通过路径名进行访问和引用
  • 同步与互斥
  • 可以是任意进程间的通信
  • 进程退出,内核中的内存也就释放了,但是有名管道文件还在。

这篇关于操作系统-进程间的四种通信(共享内存、消息队列、信号、管道)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1070583

相关文章

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

MySQL修改密码的四种实现方式

《MySQL修改密码的四种实现方式》文章主要介绍了如何使用命令行工具修改MySQL密码,包括使用`setpassword`命令和`mysqladmin`命令,此外,还详细描述了忘记密码时的处理方法,包... 目录mysql修改密码四种方式一、set password命令二、使用mysqladmin三、修改u

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

Python给Excel写入数据的四种方法小结

《Python给Excel写入数据的四种方法小结》本文主要介绍了Python给Excel写入数据的四种方法小结,包含openpyxl库、xlsxwriter库、pandas库和win32com库,具有... 目录1. 使用 openpyxl 库2. 使用 xlsxwriter 库3. 使用 pandas 库

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

使用C/C++调用libcurl调试消息的方式

《使用C/C++调用libcurl调试消息的方式》在使用C/C++调用libcurl进行HTTP请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试,libcurl提供了多种... 目录1. libcurl 调试工具简介2. 输出请求消息使用 CURLOPT_VERBOSE使用 C

四种Flutter子页面向父组件传递数据的方法介绍

《四种Flutter子页面向父组件传递数据的方法介绍》在Flutter中,如果父组件需要调用子组件的方法,可以通过常用的四种方式实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录方法 1:使用 GlobalKey 和 State 调用子组件方法方法 2:通过回调函数(Callb

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf