(1)进程间常见的几种通信方式

news/2024/4/18 23:24:47/

`

文章目录

  • 进程间的通行方式
  • 一、管道模型
  • 二、消息队列模型
  • 三、共享内存
  • 四 信号量机制
  • 五、socket


进程间的通行方式

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC)。

不同的进程之间是不可以之间进行访问的,但所属的线程可以访问进程中的数据,如何进行进程之间的互相访问?其对应的方式有以下几种。

在这里插入图片描述


一、管道模型

管道模型是linux命令行中常用的模式。

管道模型分为两类,一类是匿名管道,另一类是命名管道。

linxu命令行cat xx.txt | grep -n ‘xxx’ 这个’|'可以看作一个单向的匿名管道,使得前后两个进程之间进行通信,前一个命名的输出作为后一个命令的输入,该管道使用结束则立即销毁。命名管道在linux中以文件的形式存在,只要访问该文件就可以实现任意两个进程间的通信,命名管道可以看作是是硬盘上存在的设备文件,所以打开需要使用open(linxu中一切皆文件原则)。

管道本质上就是内核中的一个缓存,当进程创建一个管道后,Linux会返回两个文件描述符,一个是写入端的描述符,一个是输出端的描述符,可以通过这两个描述符往管道写入或者读取数据。如果想要实现两个进程通过管道来通信,则需要让创建管道的进程fork子进程,这样子进程们就拥有了父进程的文件描述符,这样子进程之间也就有了对同一管道的操作(管道应用于父子进程之间的通信)。

局限性:

半双工通信,一条管道只能一个进程写,一个进程读。
一个进程写完后,另一个进程才能读,反之同理。
管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等

管道是最简单的通信方式,也是效率最差的一种,不适合进程间频繁的交换数据。

二、消息队列模型

消息队列的通信方式可以解决进程间频繁的交换数据。

消息队列模型于在程序中使用的队列是差不多的,不同之处在于队列是同一个进程往队列里放东西拿东西。消息队列模型多应用于多线程生产者消费者模式,一端线程生产数据放入消息队列中,一端进程判断消息队列中有数据便拿出数据去处理。

A进程往消息队列写入数据后就可以正常返回,B进程需要时再去读取就可以了,效率比较高。

而且,数据会被分为一个一个的数据单元,称为消息体,消息发送方和接收方约定好消息体的数据类型,不像管道是无格式的字节流类型,这样的好处是可以边发送边接收,而不需要等待完整的数据

但是同样也有缺点,每个消息体有一个最大长度的限制,并且队列所包含消息体的总长度也是有上限的,这是其中一个不足之处。

另一个缺点是消息队列通信过程中存在用户态和内核态之间的数据拷贝问题。进程往消息队列写入数据时,会发送用户态拷贝数据到内核态的过程,同理读取数据时会发生从内核态到用户态拷贝数据的过程。

三、共享内存

共享内存解决了消息队列存在的内核态和用户态之间数据拷贝的问题。

传输一些大文件,如果采用管道或者消息队列传输大文件,涉及到重复拷贝,比较消耗性能。
因此我们开辟一块存储空间,让所有的进程都可以访问到这片存储空间,就像线程访问一样,这便是共享内存技术。
共享内存技术模拟多线程,在内存中开辟一块特殊的内存用于多个进程共享访问。也是进程间最高效的通信方式
现代操作系统对于内存管理采用的是虚拟内存技术,也就是说每个进程都有自己的虚拟内存空间,虚拟内存映射到真实的物理内存。共享内存的机制就是,不同的进程拿出一块虚拟内存空间,映射到相同的物理内存空间。这样一个进程写入的东西,另一个进程马上就能够看到,不需要进行拷贝。

共享内存技术的特别是速度快。因为它减少了很多的不必要的访问和传输。但缺点是如果很多进程对同一片存储空间进行读写,会出现一些数据乱行和脏数据问题。因此共享内存通常适合信号量机制一起使用的。

四 信号量机制

信号和信号量是两种不同的概念。

信号量可以看作一种数据操作锁,通过对临界资源的控制访问以管理进程之间的通信,PV原语操作。
临界资源:同一时间只能被同一进程访问,其他申请访问的进程只能等这一进程访问完之后才能进行访问。
信号量本质上是一个整型的计数器,用于实现进程间的互斥和同步

信号量代表着资源的数量,操作信号量的方式有两种:

P操作:这个操作会将信号量减一,相减后信号量如果小于0,则表示资源已经被占用了,进程需要阻塞等待;如果大于等于0,则说明还有资源可用,进程可以正常执行。
V操作:这个操作会将信号量加一,相加后信号量如果小于等于0,则表明当前有进程阻塞,于是会将该进程唤醒;如果大于0,则表示当前没有阻塞的进程。

信号量实现互斥:
信号量初始化为1
进程 A 在访问共享内存前,先执行了 P 操作,由于信号量的初始值为 1,故在进程 A 执行 P 操作后信号量变为 0,表示共享资源可用,于是进程 A 就可以访问共享内存。
若此时,进程 B 也想访问共享内存,执行了 P 操作,结果信号量变为了 -1,这就意味着临界资源已被占用,因此进程 B 被阻塞。
直到进程 A 访问完共享内存,才会执行 V 操作,使得信号量恢复为 0,接着就会唤醒阻塞中的线程 B,使得进程 B 可以访问共享内存,最后完成共享内存的访问后,执行 V 操作,使信号量恢复到初始值 1。

信号量实现同步:
由于多线程下各线程的执行顺序是无法预料的,有些时候我们希望多个线程之间能够密切合作,这时候就需要考虑线程的同步问题。
信号量初始化为0
如果进程 B 比进程 A 先执行了,那么执行到 P 操作时,由于信号量初始值为 0,故信号量会变为 -1,表示进程 A 还没生产数据,于是进程 B 就阻塞等待;
接着,当进程 A 生产完数据后,执行了 V 操作,就会使得信号量变为 0,于是就会唤醒阻塞在 P 操作的进程 B;
最后,进程 B 被唤醒后,意味着进程 A 已经生产了数据,于是进程 B 就可以正常读取数据了。

信号

在Linux中,为了响应各种事件,提供了几十种信号,可以通过kill -l命令查看。

如果是运行在shell终端的进程,可以通过键盘组合键来给进程发送信号,例如使用Ctrl+C产生SIGINT信号,表示终止进程。

如果是运行在后台的进程,可以通过命令来给进程发送信号,例如使用kill -9 PID产生SIGKILL信号,表示立即结束进程。

五、socket

与前面几种进程建通信方式不同,它们都是在同一台主机上进行进程间通信,如果想要跨网络和不同主机上的进程进行通信,则需要用到socket(套接字)。套接字用于多个进程之间的网络传输。可以是单机多进程也可以是不同机器上的多进程通信。打开的socket在linux下也是以文件描述符fd存在。服务端创建套接字,绑定ip端口,监听端口号,等待客户端调用,客户端创建之后与服务端TCP三次握手建立连接完成,双方就可以发送和接收数据。

在这里插入图片描述

  1. 服务端和客户端初始化Socket,得到文件描述符
  2. 服务端调用bind,绑定IP和端口
  3. 服务端调用listen,进行监听
  4. 服务端调用accept,等待客户端连接
  5. 客户端调用connect,向服务端发起连接请求。(TCP三次握手)
  6. 服务端调用accept返回用于传输的Socket的文件描述符(和第一点得到的Socket不同)
  7. 客户端使用write写入数据,服务端调用read读取数据
  8. 客户端断开连接时会调用close,服务端也会调用close(TCP四次挥手)

这里要注意的是,调用accept,连接成功得到的Socket是用来传输数据的,而第一次初始化Socket是用来监听的,是两个不同作用的Socket。


http://www.ppmy.cn/news/1068794.html

相关文章

阀门状态监测和预测性维护的原理和实施步骤

随着制造业数字化转型的推进,预测性维护(Predictive Maintenance,简称PdM)成为提高生产效率和设备可靠性的关键策略之一。在流程工厂中,阀门作为重要的设备之一,起着控制流体流动的关键作用。本文将探讨如何…

ABeam×Startup | 德硕管理咨询(深圳)创新研究团队拜访微漾创客空间

近日,德硕管理咨询(深圳)(以下简称:“ABeam-SZ”)创新研究团队前往微漾创客空间(以下简称:微漾)拜访参观,并展开合作交流。会议上,双方相互介绍了…

掌握C/C++协程编程,轻松驾驭并发编程世界

一、引言 协程的定义和背景 协程(Coroutine),又称为微线程或者轻量级线程,是一种用户态的、可在单个线程中并发执行的程序组件。协程可以看作是一个更轻量级的线程,由程序员主动控制调度。它们拥有自己的寄存器上下文…

Matlab(结构化程式和自定义函数)

目录 1.脚本编辑器 2.脚本流 2.1 控制流 2.2 关系(逻辑)操作符 3.脚本与函数 1.脚本编辑器 Matlab的命名规则: 常用功能: 智能缩进: 在写代码的时候,有的时候代码看起来并不是那么美观(可读性…

Flink流批一体计算(19):PyFlink DataStream API之State

目录 keyed state Keyed DataStream 使用 Keyed State 实现了一个简单的计数窗口 状态有效期 (TTL) 过期数据的清理 全量快照时进行清理 增量数据清理 在 RocksDB 压缩时清理 Operator State算子状态 Broadcast State广播状态 keyed state Keyed DataStream 使用 k…

基于django框架的学生选课系统jsp学校教务信息java源代码Mysql

本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 基于django框架的学生选课系统 系统有2权限&#xff…

服务间通过Feign相互调用报错,参数是MultiparFile、参数是POJO报错

目录 1.Feign传文件报错,Feign不支持上传文件需要借助外面的依赖才可以实现上传 2.服务之间通过Feign相互调用传递DTO(实体对象)报错 1.Feign传文件报错,Feign不支持上传文件需要借助外面的依赖才可以实现上传 具体报错内容: FileUploadException: the request was reje…

服务器数据库中了locked勒索病毒怎么办,locked勒索病毒恢复工具

最近一段时间网络上的locked勒索病毒非常嚣张,自从6月份以来,很多企业的计算机服务器数据库遭到了locked勒索病毒的攻击,起初locked勒索病毒攻击用友畅捷通T用户,后来七月份开始攻击金蝶云星空客户,导致企业的财务系统…

数据增强:提高机器学习性能的有效技巧

文章目录 数据增强的原理常用的数据增强技术图像数据增强文本数据增强音频数据增强 数据增强的代码示例拓展应用与挑战结论 🎉欢迎来到AIGC人工智能专栏~数据增强:提高机器学习性能的有效技巧 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页&a…

Docker修改容器ulimit的全部方案及各方案的详细步骤

要修改Docker容器的ulimit(用户资源限制),有以下三种方案,每个方案的详细步骤如下: 方案一:在Dockerfile中设置ulimit 打开您的Dockerfile。在文件中添加以下命令来修改ulimit:RUN ulimit -n …

259_C++_`std::dynamic_pointer_cast` 是 C++ 中的一个模板函数,用于进行动态类型转换操作,主要用于智能指针的转换’

std::dynamic_pointer_cast 是 C++ 中的一个模板函数,用于进行动态类型转换操作,主要用于智能指针的转换。它的作用是将一个派生类类型的智能指针转换为基类类型的智能指针,或者将基类类型的智能指针转换为派生类类型的智能指针。这个操作会在运行时进行类型检查,确保转换是…

day-03 基于TCP的服务器端/客户端

一.理解TCP和UDP TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)是两种常见的传输层协议,用于在计算机网络中提供可靠的数据传输。 1.TCP: 连接导向:TCP是一种面向连接的…

Python Flask token身份认证

首先安装依赖: pip install flask-jwt-extended 然后在主应用中(项目入口文件)加入以下代码: from flask import Flask from flask_jwt_extended import JWTManager #引入依赖 app Flask(__name__) app.config[JWT_SECRET_KEY…

LeetCode第11~15题解

CONTENTS LeetCode 11. 盛最多水的容器(中等)LeetCode 12. 整数转罗马数字(中等)LeetCode 13. 罗马数字转整数(简单) LeetCode 11. 盛最多水的容器(中等) 【题目描述】 给定一个长…

列表类控件虚拟化

WPF列表控件提供的最重要的功能是UI虚拟化(WPF编程宝典说的)。所有的WPF列表控件(所有继承自ItemsControl的控件,包括ListBox、CombBox、ListView、TreeView、DataGrid)都支持UI虚拟化。 UI虚拟化的支持实际上没有被构…

SAP-FI-会计凭字段替代OBBH

会计凭证替代OBBH 业务:文本必须等于某个字段的值,例如凭证日期 关闭确认功能,输入OBBH 双击“替代”进入功能配置,或者用GGB1,用GGB1的功能更多。 点击行项目,点击“新建替换”保存 点击新建YXL7331,点击…

详解过滤器Filter和拦截器Interceptor的区别和联系

目录 前言 区别 联系 前言 过滤器(Filter)和拦截器(Interceptor)都是用于在Web应用程序中处理请求和响应的组件,但它们在实现方式和功能上有一些区别。 区别 1. 实现方式: - 过滤器是基于Servlet规范的组件,通过实现javax.servlet.Filt…

【高精度加法】

高精度加法 #include<iostream> #include<vector>using namespace std;vector<int> add(vector<int>& A,vector<int>& B){if(A.size()<B.size()) return add(B,A);vector<int> C;int t 0;for(int i0;i<A.size();i){tA[i…

橙河:海外賺美金的项目有哪些?

大家好&#xff0c;我是橙河老师。现在呢&#xff0c;很多人去国外打工&#xff0c;大家在短视频上也经常能看到&#xff0c;他们在国外挣了几年钱&#xff0c;回来就能买车买房。 其实呢&#xff0c;他们在国外的工作&#xff0c;工资也就是几千块一个月&#xff0c;不过他们…

javacv基础03-调用本机摄像头并截图保存到本地磁盘

基于基础02 的基础上对视频进行取帧保存 代码如下&#xff1a; package com.example.javacvstudy;/*** 本地摄像头截图*/import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.FrameGrabber; import org.bytedeco.javacv.OpenCVFrameConverter; import org.b…