【linux深入剖析】进程间通信


🍁你好,我是 RO-BERRY
📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油

在这里插入图片描述


目录

  • 1.进程间通信目的
  • 2. 什么是进程间通信
  • 3. 进程间通信发展
  • 4.如何进行进程间通信
    • 4.1 一般规律
    • 4.2 具体做法
  • 5.进程间通信分类
  • 6. 管道
    • 匿名管道
    • 用fork来共享管道原理
    • 站在文件描述符角度-深度理解管道
    • 验证管道通信代码


1.进程间通信目的

两个进程之间,可以进行“数据”的直接传递吗?不能!进程具有独立性

那么为什么需要进程间通信呢?

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

在很多场景之间,两个进程需要进行数据传输,比如:A进程负责获取网络中的数据,但是它并不会去处理这份数据,而B进程为只负责处理数据,这样就可以实现多进程的并发

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

有一部分进程需要进行共享一份资源,以便于两进程共同访问共同完成一件事情,比如说:我们玩游戏,多玩家在同一局游戏中,我们看到的数据都是一模一样的,我们的每个用户也就是一个进程,我们对于地图资源进行的是共享

  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程止时要通知父进程)。
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变

2. 什么是进程间通信

  • 进程间通信(Inter-process Communication,IPC)是指在多道程序环境下,进程间进行数据交换和信息传递的一种机制或方法。在现代操作系统中,进程是系统资源分配的基本单位,不同进程之间需要相互合作和通信,才能完成各种任务。进程间通信是实现进程间协作的重要手段。

  • 常用的进程间通信方式有管道、消息队列、共享内存、信号量和套接字等。管道是一种半双工的通信方式,消息队列是一种异步通信方式,共享内存是一种高效的通信方式,信号量是一种用于同步进程的通信方式,套接字是一种网络通信方式。


3. 进程间通信发展

进程间通信是指不同进程之间的数据交换和共享,是操作系统中非常重要的一个概念。随着计算机技术的发展,进程间通信也经历了多个发展阶段。

  • 第一阶段是管道,它是Unix系统中最早的进程间通信方式,可以在两个相关进程之间传递数据。

  • 第二阶段是信号,它是Unix系统中另一种进程间通信方式,用于通知接收进程某个事件已经发生。

  • 第三阶段是共享内存,它可以允许多个进程访问同一块物理内存,从而实现数据共享。

  • 第四阶段是消息队列,它可以在不同进程之间传递消息,实现进程间通信。

  • 第五阶段是套接字,它可以在不同主机之间传递数据,并且支持多种通信协议。

  • 第六阶段是远程过程调用(RPC),它允许程序员在不同计算机上运行的程序之间进行交互。


4.如何进行进程间通信

4.1 一般规律

  • 进程间通信的本质:让不同的进程,看到同一份资源(一般都是由OS提供)

进程间通信需要一个另外的交换数据的空间(内存)

此交换空间不能由通信双方任何一方进行提供,如果提供了空间,让对方进程来进行访问,这就有违背进程独立性,所以我们需要另一个额外空间进行数据的传输,这种事情会有OS来进行操作


4.2 具体做法

OS提供的“空间”有不同的样式,这决定了不同的通信方式

常见通信方式:

  1. 管道(匿名和命名)
  2. 共享内存
  3. 消息队列
  4. 信号量

5.进程间通信分类

🍁管道

  • 匿名管道pipe
  • 命名管道

🍁System V IPC

System V IPC是指System V操作系统提供的进程间通信(IPC)机制,它允许进程在不同的计算机系统之间进行通信和同步。System V IPC主要包括三种类型的通信机制:消息队列、共享内存和信号量。

  • System V 消息队列
  • System V 共享内存
  • System V 信号量

🍁POSIX IPC

POSIX IPC 是指可移植操作系统接口(Portable Operating System Interface,缩写为POSIX)中的进程间通信(Inter-Process Communication,缩写为IPC)机制。它提供了一组标准的函数和数据结构,用于在不同的进程间进行数据交换和同步操作。常用的 POSIX IPC 包括消息队列、共享内存、信号量等。使用 POSIX IPC 可以实现不同进程之间的数据共享和通信,进而实现更加复杂的多进程协作模式。

  • 消息队列
  • 共享内存
  • 信号量
  • 互斥量
  • 条件变量
  • 读写锁

6. 管道

  • 管道是Unix中最古老的进程间通信的形式。
  • 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”

管道是一种进程间通信机制,它可以用来在不同进程间传递数据。在底层实现上,管道其实是一种内核缓冲区,它由两个文件描述符(文件句柄)表示,一个用于读取,一个用于写入。当一个进程向管道中写入数据时,数据会被存储到内核缓冲区中,另一个进程则可以从同一个管道中读取这些数据。

管道底层实现的关键是通过操作系统提供的内核缓冲区实现进程间的数据传输。管道有两个缓冲区,分别用于存储读取和写入的数据。当写入进程向管道中写入数据时,数据会被存储到写入缓冲区中。如果写入缓冲区已满,则写入进程会被阻塞,直到有足够的空间来存储数据。当读取进程从管道中读取数据时,数据会从读取缓冲区中读取。如果读取缓冲区为空,则读取进程也会被阻塞,直到有新的数据可供读取。

需要注意的是,管道具有单向性,即数据只能从一个方向流动。如果需要双向通信,则需要创建两个管道。同时,在管道中传递的数据是没有结构的字节流,因此需要约定好传递的数据格式以及数据长度。

匿名管道

#include <unistd.h>
功能:创建一无名管道
原型
int pipe(int fd[2]);
参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码

这个函数让我们不需要向磁盘中刷新并且磁盘中并不存在文件,其本质就是会创建一个内存级的文件,这个文件没有名字,为匿名文件(管道)

匿名管道如何做到让不同的进程看到同一份资源?

就是利用了创建子进程,子进程会创建父进程的相关属性信息,匿名管道可以(只能)进行具有血缘关系的进程,进行进程间通信,常用于父子

在这里插入图片描述
实例代码

例子:从键盘读取数据,写入管道,读取管道,写到屏幕
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
	int fds[2];
	char buf[100];
	int len;
	if (pipe(fds) == -1)
		perror("make pipe"), exit(1);
	// read from stdin
	while (fgets(buf, 100, stdin)) {
		len = strlen(buf);
		// write into pipe
		if (write(fds[1], buf, len) != len) {
			perror("write to pipe");
			break;
		}
		memset(buf, 0x00, sizeof(buf));

		// read from pipe
		if ((len = read(fds[0], buf, 100)) == -1) {
			perror("read from pipe");
			break;
		}
		// write to stdout
		if (write(1, buf, len) != len) {
			perror("write to stdout");
			break;
		}
	}
}

用fork来共享管道原理

在这里插入图片描述

站在文件描述符角度-深度理解管道

在这里插入图片描述

为什么父进程最开始就要按照r和w打开同一个文件呢?
这是因为管道只允许一个人读,一个人写。

验证管道通信代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

void writer(int wfd)
{
  const char *str ="hello father, I am child";
  char buffer[128];
  int cnt = 0;
  pid_t pid  = getpid();
  while(1)
  {
    snprintf(buffer, sizeof(buffer),"message: %s,pid: %d,count: %d \n", str, pid, cnt);

    write(wfd,buffer,strlen(buffer)+1);
    cnt++;
    sleep(1);
  }
}
void reader(int rfd)
{
  char buffer[1024];
  while(1)
  {
    ssize_t n = read(rfd, buffer, sizeof(buffer)-1);
    (void)n;   //读取但是没有用
    printf("father get a message: %s", buffer);
  }
}

int main()
{
  int pipefd[2];
  int n = pipe(pipefd);
  if(n<0) return 1;
  printf("pipefd[0]: %d, pipefd[1]: %d\n", pipefd[0]/*read*/, pipefd[1])/*write*/; //创建管道

  //父子进程
  pid_t id=fork();
  if(id == 0)
  {
    //child 实现W 关闭读取保留写入
    close(pipefd[0]);
    
    writer(pipefd[1]);

    exit(0);
  }

  //father实现r
  close(pipefd[1]);
  
  reader(pipefd[0]);
  wait(NULL);
  return 0;
}

在这里插入图片描述
这里可以在左边看到有两个进程同时运行,初步实现管道通信,子进程可以写给父程序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/663559.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大语言模型应用与传统程序的不同

大语言模型&#xff08;LLM&#xff09; 被描述的神乎其神&#xff0c;无所不能&#xff0c;其实&#xff0c;大语言模型只是一个模型&#xff0c;它能够理解和生成自然语言&#xff0c;唯有依靠应用程序才能够发挥作用。例如&#xff0c;基于大模型可以构建一个最简单的会话机…

搜狐视频专访神工坊创始人任虎:以先进计算技术为引擎,引领新一代CAE革新之路

搜狐视频采访 神工坊&#xff08;无锡&#xff09;数字技术有限公司&#xff0c;源自国家超级计算无锡中心&#xff08;始于2016年&#xff09;&#xff0c;于2022年8月在无锡成立&#xff0c;是一家以高性能计算等先进计算技术推动新一代CAE技术革新的公司。 在全国科技工作者…

[Algorithm][动态规划][子序列问题][最长递增子序列][摆动序列]详细讲解

目录 0.子序列 vs 子数组1.最长递增子序列1.题目链接2.算法原理详解3.代码实现 2.摆动序列1.题目链接2.题目链接3.代码实现 0.子序列 vs 子数组 子序列&#xff1a; 相对顺序是跟源字符串/数组是一致的但是元素和元素之间&#xff0c;在源字符串/数组中可以是不连续的一般时间…

python绘制piper三线图

piper三线图 Piper三线图是一种常用于水化学分析的图表&#xff0c;它能够帮助我们理解和比较水样的化学成分。该图表由三个部分组成&#xff1a;两个三角形和一个菱形。两个三角形分别用于显示阳离子和阴离子的相对比例&#xff0c;而菱形部分则综合显示了这些离子比例在水样…

蓝屏,联想持续很久停留在正在准备windows请勿关闭计算机怎么办?解决方案如下。

联想小新&#xff0c;连续出现两次间隔一年半遇上上述问题&#xff0c;按电源键后也会出现下述情况&#xff0c;遇到问题不要着急&#xff0c;偶尔电脑也会生个小病什么的。 附上最后的解决办法&#xff1a;两次都成功┗|&#xff40;O′|┛ 嗷~~ 按上述步骤执行后重启计算机等…

Buffer Pool运行机制理解

Buffer Pool机制理解 一、为什么使用Buffer Pool&#xff1f; 众所周知&#xff0c;磁盘数据是以数据页的形式来去读取的&#xff0c;一个数据页默认大小 16K&#xff0c;也就是说你本意只想读取一行数据&#xff0c;但是它会给你加载一页的数据到buffer pool里面。这样的话就…

高等教育的AI革新:OpenAI面向大学推出ChatGPT Edu

OpenAI推出了ChatGPT Edu&#xff0c;这是一个为大学设计的专用版本&#xff0c;旨在让学生、教职员工、研究人员和校园运营能够负责任地使用AI。 ChatGPT Edu 将AI技术引入了教育领域&#xff0c;其建立在GPT-4o的基础上&#xff0c;它不仅能够处理文本和图像&#xff0c;还…

xss漏洞学习(题解)

1.简单知识点回顾 XSS允许恶意web用户将代码植入到提供给其它用户使用的页面中。 特点&#xff1a;能注入恶意的HTML/JavaScript代码到用户浏览器网址上&#xff0c;从而劫持会话 类型&#xff1a; DOM型&#xff1a;属于反射型的一种&#xff0c;利用非法输入来闭合对应的h…

【源码+文档+调试讲解】火车票订票系统设计与实现

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装火车票订票系统软件来发挥其高效地信息处理的作用&#xff…

车灯罩外壳破裂破损掉角等修复,修复后合面合壳密封用泰达克车灯无痕修复UV胶车灯合面密封UV胶。

一&#xff1a;专用车灯无痕修复UV胶 车灯无痕修复专用胶主要成份是改性丙烯酸UV树脂&#xff0c;主要应用在车灯的专业无痕修复领域。 具有如下特点&#xff1a; 固化时间快&#xff0c;通过紫外光照射5-15秒固化。 高度透明&#xff0c;固化后透光率高&#xff0c;折射率接…

佳能R6M2断电覆盖的恢复方法

佳能R6是佳能R系列中的一款高端机&#xff0c;最近两年佳能和索尼不断斗法&#xff0c;都号称自己的新机型能达到影视级&#xff0c;不过目前看貌似索尼更胜一筹。下边这个案例是文件拍摄时断电&#xff0c;结果变成0字节&#xff0c;然后覆盖了部分数据。 故障存储:128G存储卡…

新加坡裸机云站群服务器稳定性怎么样

新加坡裸机云站群服务器的稳定性在云计算领域备受关注&#xff0c;这得益于其卓越的硬件配置、先进的数据中心设计、优质的网络连接以及严格的管理措施。以下是对新加坡裸机云站群服务器稳定性的详细科普&#xff1a; 一、硬件与配置 新加坡裸机云站群服务器通常采用高性能的物…

12V升20V3.5A升压恒压WT3207

12V升20V3.5A升压恒压WT3207 WT3207是一款高效PWM升压控制器&#xff0c;采用SO-8封装设计&#xff0c;专为低输入电压应用优化。该控制器支持5V至36V的宽输入电压范围&#xff0c;使其能够有效提升12V、15V和19V系统的电压水平&#xff0c;特别适合于两节或三节锂离子电池供电…

SpringBoot:基于SpringBoot实现多数据源动态切换

一、前言 Spring Boot 多数据源&#xff0c;也称为动态数据源&#xff0c;是指在Spring Boot项目中配置多个数据源&#xff0c;以支持不同的数据库访问需求。这种配置方式在项目开发逐渐扩大、单个数据源无法满足项目支撑需求时变得尤为重要。 二、目的 配置多数据源的主要目…

FinRobot:一个由大型语言模型(LLM)支持的新型开源AI Agent平台,支持多个金融专业AI Agent

财务分析一直是解读市场趋势、预测经济结果和提供投资策略的关键。这一领域传统上依赖数据&#xff0c;但随着时间的推移&#xff0c;越来越多地使用人工智能&#xff08;AI&#xff09;和算法方法来处理日益增长的复杂数据。AI在金融领域的作用显著增强&#xff0c;它自动化了…

vm:为虚拟机配置多个虚拟网卡(ubuntu20.04)

前言&#xff1a; 环境&#xff1a;虚拟机 ubuntu 20.04 要求&#xff1a;如标题&#xff0c;但是这里针对的是 ubuntu 20.04&#xff0c;对于其他操作系统&#xff0c;可以找一下其他操作系统对应的配置文件是什么 vm 添加虚拟网卡 首先进入 vm&#xff1a; 点击设置&#xf…

【AI大模型】如何让大模型变得更聪明?基于时代背景的思考

【AI大模型】如何让大模型变得更聪明 前言 在以前&#xff0c;AI和大模型实际上界限较为清晰。但是随着人工智能技术的不断发展&#xff0c;基于大规模预训练模型的应用在基于AI人工智能的技术支持和帮助上&#xff0c;多个领域展现出了前所未有的能力。无论是自然语言处理、…

EPSON爱普生RTC RA8900CE/RA8000CE+松下Panasonic电池组合

RTC是一种实时时钟&#xff0c;用于记录和跟踪时间&#xff0c;具有独立供电和时钟功能。在某些应用场景中&#xff0c;为了保证RTC在断电或者其他异常情况下依然能够正常工作&#xff0c;需要备份电池方案来提供稳定的供电。本文将介绍EPSON爱普生RTC RA8900CE/RA8000CE松下Pa…

laravel项目配置Facades Redis自动补全,方法查看

问题原因: 因为Laravel的Redis连接实例是通过RedisManger的工厂类创建的,返回的是一个mixin的类型,因此在IDE中不能自动补全Redis的方法,缺少这个功能,使用起来有些麻烦,尤其是Redis有数十个方法,每个方法也有不少参数。 相关部分的代码如下: /*** @mixin \Illumina…

super().__init__() 来自于哪个PEP

super() 的简化用法&#xff08;即不带参数的 super()&#xff09;是在 Python 3 中引入的。这个改进是由 PEP 3135 规范化的。 PEP 3135: New Super PEP 3135 标题为 “New Super”。它介绍了一种新的方式来调用超类的方法&#xff0c;即不再需要显式地传递当前类和实例&…