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

Linux学习之路 -- 进程 -- 进程间通信 -- 管道通信

本文主要介绍进程通信中的管道通信。

前面我们学习进程的过程中,我们知道,进程是具有独立性的。这也就导致了进程不能够直接地把数据进行传递。为了实现进程之间地通信,我们就需要通过另外地方式来实现进程之间数据地传递。

1.进程通信的目的

首先,在正式学习进程间通信前,我们需要了解进程间通信的目的

<1>数据传输:一个进程需要将它的数据发送给另一个进程
<2>资源共享:多个进程之间共享同样的资源。
<3>通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
<4>进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

总的来说,就是我们往往需要多个进程进行协作,完成一些事情。

2.管道通信的相关原理

1.一般规律

        假设我们有两个进程,我们要实现这两个进程之间的数据通信,肯定是不能把一个进程上的数据直接拷贝到另一个进程的空间上,这样的作法无法保证进程之间的独立性。所以我们需要通过一块(内存)空间来实现两个进程之间的数据。同时,这块空间还不能由通信双方任何一个提供,如果是由其中一个提供,那就允许另一个进程访问,这会破坏进程的独立性。

        所以进程间通信的本质就是让不同的进程看到同一块空间资源,这块资源一般由OS提供。而OS提供的“空间”有不同的样式,就决定了不同的通信方式。
2.实现方式

        前面我们在介绍文件时,我们了解到进程是通过文件描述符表来控制文件的。其中一个文件被不同的方式打开是要占据不同的文件描述符的,而我们再创建一个子进程时,文件描述符表也会跟着创建一份,但是里面的内容是和父进程一致的。这两个进程都会指向同一个文件。


这里父子进程就指向了同一块空间,并且这块空间是由操作系统提供,说明我们可以通过文件的方式,来实现进程之间的通信。这种通信的方式就叫做管道通信

管道通信只能被设计成单向的通信,也就是一个进程读,另一个进程写。正常情况下,我们要以读方式和写方式分别打开两次文件,在不同的进程中关闭不同的文件描述符,这样做是为了让父子进程都可以当作读端或写端。我们把父进程以读方式打开的文件描述符关闭,把子进程以写方式打开的文件描述符关闭,这样就可以实现父进程写,子进程读。

相关接口

为了支持管道通信,系统给我们提供相关的系统接口

<1>pipe

int pipefd[2]是输出型参数,用于存放两个fd,分别是以读和写方式打开的文件描述符。通过该接口,我们就不需要向磁盘中刷新和向磁盘中创建文件。通俗的说,就是创建内存级的文件,叫匿名文件(管道)。这个文件不用把数据加载到磁盘,也不用实现标准输入、输出、错误等等。

匿名管道通信的特点,就是只能让有血缘关系的进程,进行进程间通信(常用于父子进程)

这个接口如果返回零,那么就表示调用成功,如果失败了,就返回-1。如果成功调用,那么pipefd[0]中存放的是读端的文件描述符,而pipefd[1] 中存放的是写端的文件描述符。

下面我们可以用一段代码验证上述的结论

#include<stdio.h>
#include<unistd.h>int main()
{int pipefd[2];int n = pipe(pipefd);if(n < 0) return 1;printf("%d %d\n",pipefd[0],pipefd[1]);return 0;
}

运行结果

下面简单实现一下,用父子进程间进行通信

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>void Write(int wfd)
{const char* str = "hello linux";char buffer[1024];int pid = getpid();while(1){snprintf(buffer,sizeof(buffer),"pid:%d str:%s\n",pid,str);write(wfd,buffer,sizeof(buffer));}}
void Read(int rfd)
{int cnt = 20;char buffer[1024];while(cnt--){ssize_t n = read(rfd, buffer,sizeof(buffer));(void)n;printf("%s", buffer);sleep(1);}
}int main()
{int pipefd[2];int n = pipe(pipefd);if(n < 0) return 1;printf("%d %d\n",pipefd[0],pipefd[1]);pid_t id = fork();//写端if(id == 0){close(pipefd[0]);Write(pipefd[1]);exit(0);}//父进程close(pipefd[1]);Read(pipefd[0]);wait(NULL);
}

 运行结果

 这样我们就实现父子进程的简单通信。

关于管道通信的几种情况。

<1>管道内部没有数据 && 子进程不关闭自己的写端文件fd,读端(父进程)就要阻塞等待,直到管道有数据。

<2>管道内部被写满了 && 读端(父进程)不关闭自己的fd,写段(子进程)写满之后,就要阻塞等待。管道的默认大小是4kB(unbantu 20.04版本下)。在这种情况下,读端会尽可能多的读取数据,当读取到一定数量的数据时,写端又会重新向管道写入数据。

<3>对于写端而言,不写了&&关闭了管道,读端会将pipe中的数据读完,最后就会读到返回值为0,表示读结束,类似与读到文件的结尾。

<4>读端不读&&关闭,写端在写,OS会直接终止写入的进程(子进程),通过信号(13 SIGPIPE)进程终止。(下图是让读端关闭(父进程),写端(子进程)继续写,并打印出退出码和退出信号)。

管道的几种的特性

<1>自带同步机制,也就是执行时有一定的顺序。

<2>有血缘关系之间的通信

<3>管道是面向字节流的(读端和写端的次数没有直接的联系)

<4>父子进程退出,管道自动的释放,文件的声明周期是随进程的。

<5>管道只能单向通信。半双工的一种特殊情况

而我们学习的命令行管道,本质上也就是本文所述的管道。而我们在使用命令行管道时,一个命令就是一个进程,一个竖划线就是一个管道,这些进程的父进程都是bash进程。

应用场景:进程池。

由于我们每次创建进程都要向系统中进行申请,这个过程比较麻烦,所以我们可以直接先申请多个进程,由一个主进程进行控制,每个进程都和父进程之间创建管道,这个就叫进程池。在创建完毕后,我们可以进程池内的进程分配任务,一个进程不能执行全部的任务,而是要让所有的进程都执行一些任务,这个分配规则就叫负载均衡。

命名管道

匿名管道适用于父子进程之间的通信,而我们如果要在完全不相干的两个进程之间进行通信,就需要使用命名管道。

如上图所示,当我们进程A和进程B以不同的方式打开file.txt时,正常来说会生成两个文件缓冲区,但是由于两个文件缓冲区内容是一样的,所以我们就只需要一个文件缓冲区即可。由于此时的文件缓冲区是不需要向文件中刷新数据的(会浪费空间,而且没必要),所以文件缓冲区就可以作为一个管道,实现两个进程之间的通信。

如何保障两个打开的是同一个文件呢(也就是确保同一缓冲区)?我们可以使用文件的路径+文件名的方式锁定文件,这样可以保证打开的就是同一文件。

具体方法:

我们可以使用mkfifo命令创建管道,然后在实现两个进程之间的通信。

相关文章:

Linux学习之路 -- 进程 -- 进程间通信 -- 管道通信

本文主要介绍进程通信中的管道通信。 前面我们学习进程的过程中&#xff0c;我们知道&#xff0c;进程是具有独立性的。这也就导致了进程不能够直接地把数据进行传递。为了实现进程之间地通信&#xff0c;我们就需要通过另外地方式来实现进程之间数据地传递。 1.进程通信的目…...

GB/T 38082-2019 生物降解塑料购物袋检测

生物降解塑料购物袋是指以生物降解树脂为主要原料制得的&#xff0c;具有提携结构的&#xff0c;在销售、服务等场所用于盛装及携提商品的袋制品。 GB/T 38082-2019 生物降解塑料购物袋检测项目&#xff1a; 检测项目 测试标准 尺寸偏差 GB/T 38082 感官 GB/T 38082 提掉…...

docker数据卷和资源控制

目录 数据卷 实现数据卷 宿主机和容器之间进行数据共享 容器与容器之间进行数据共享 容器互联 docker容器的资源控制 cpu 1.设置cpu资源控制&#xff08;比重&#xff09; 2. 设置cpu的资源占用比&#xff08;权重&#xff09; 3.设置容器绑定cpu 内存 1.内存限制 …...

Kafka系统及其角色

Apache Kafka系统介绍 Apache Kafka 是由 LinkedIn 公司最初开发的一个高性能、分布式的消息传递系统。它被设计为一个可扩展、持久、分布式的流式处理平台&#xff0c;以满足 LinkedIn 在实时数据处理方面的需求 。Kafka 的诞生源于 LinkedIn 需要处理海量数据时现有消息队列系…...

从零开始构建霸王餐返利APP的技术路线与挑战

从零开始构建霸王餐返利APP的技术路线与挑战 大家好&#xff0c;我是阿可&#xff0c;微赚淘客系统及省赚客APP创始人&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在电商领域&#xff0c;霸王餐返利APP作为一种新兴的商业模式&#xff0c;为用…...

安装Jmeter,配置jdk

注意点: java的jdk和jmeter的版本相匹配 ! ! ! 目前我使用的是1.8的的,jmeter使用的是5.6.3 JDK下载地址&#xff1a;https://www.oracle.com/cn/java/technologies/downloads 别管,直接傻瓜式安装点点就完了... 1.电脑-属性-高级系统设置-环境变量 2.系统变量-新建-变量…...

Aria2@RPC下载@Alist批量下载

文章目录 abstractAria2 RPC 概述RPC 的主要功能在线文档aria2的配置文件与启动选项使用配置文件设置aria2 rpc功能Aria2关于rpc的离线文档 Aria2 RPC 重要和常用选项1. enable-rpc2. rpc-listen-port3. rpc-secret4. rpc-listen-all5. rpc-allow-origin-all6. rpc-max-request…...

神经串联式语音转换:对基于串联的单次语音转换方法的再思考 论文笔记

NEURAL CONCATENATIVE SINGING VOICE CONVERSION: RETHINKING CONCATENATION-BASED APPROACH FOR ONE-SHOT SINGING VOICE CONVERSION 笔记 发现问题&#xff1a; 在any-to-any的转换中,由于内容和说话人音色的解耦不足,导致源说话人的音色部分仍保留在转换后的音频中&#x…...

机器学习(1)--数据可视化

文章目录 数据可视化作用可视化方法实现可视化 总结 数据可视化 数据可视化是将数据以图形、图像、动画等视觉形式表示出来&#xff0c;以便人们能够更直观地理解、分析和交流数据中的信息。 作用 一个整理的好好的数据&#xff0c;我们为什么要将其可视化呢&#xff1f;将它…...

docker部署Prometheus、Grafana

docker部署Prometheus 1、 拉取prometheus镜像 docler pull prom/prometheus 遇到问题&#xff1a;注意下科学上网。 2、将prometheus配置文件放在外面管理 prometheus.yml global:scrape_interval: 15sevaluation_interval: 15salerting:alertmanagers:- static_configs:-…...

5.mysql多表查询

MYSQL多表查询 MYSQL多表查询1.多表关系笛卡尔积 2. 多表查询概述2.1 内连接2.2 外连接2.3自连接联合查询union &#xff0c;union all 2.4子查询2.4.1标量子查询2.4.2列子查询2.4.3行子查询2.4.4表子查询 MYSQL多表查询 create table student(id int auto_increment primary …...

【前端面试】挖掘做过的nextJS项目(上)

为什么使用nextJS 需求: 快速搭建宣传官网 1.适应pc、移动端 2.基本的路由跳转 3.页面渲染优化 4.宣传的图片、视频资源的加载优化 5.seo优化 全栈react web应用、 tailwind css原子工具的支持&#xff0c;方便书写响应式ui app router(React 服务器组件)支持服务器渲…...

【Unity-UGUI】UGUI知识汇总

目录 前言1 UGUI系统原理2 事件系统2.1 EventSystem2.2 InputModules2.3 Raycasters2.4 协作 3 UGUI系统的组件3.1 Image和RawImage3.2 Mask和RectMask2D 扩展UI穿透问题 前言 记录一些最近学到的有关UGUI的知识。 参考 知乎&#xff1a;6千字带你入门UGUI源码 书籍&#xff…...

JavaScript性能测试:策略、工具与实践

在Web开发中&#xff0c;性能测试是确保应用程序达到预期响应速度和处理能力的关键步骤。JavaScript作为构建交互式Web应用的核心语言&#xff0c;其性能直接影响用户体验。本文将详细介绍如何使用JavaScript进行性能测试&#xff0c;包括性能测试的基本概念、测试类型、工具、…...

嵌入式软件开发学习一:软件安装(保姆级教程)

资源下载&#xff1a; 江协科技提供&#xff1a; 资料下载 一、安装Keil5 MDK 1、双击.EXE文件&#xff0c;开始安装 2、 3、 4、此处尽量不要安装在C盘&#xff0c;安装路径选择纯英文&#xff0c;防止后续开发报错 5、 6、 7、弹出来的窗口全部关闭&#xff0c;进入下一步&a…...

SpringMVC学习中遇到的不懂注解记录

文章目录 Autowrite 和 ResourceQualifier 和 PrimaryPathVariableController、Service、Repository 和 Component Autowrite 和 Resource 我们先讲讲 Autowrite 注解 吧。 public class StudentService3 implements IStudentService {//Autowiredprivate IStudentDao studentD…...

Java面试题--分布式锁

分布式锁 你说一下什么是分布式锁 分布式锁是在分布式/集群环境中解决多线程并发造成的一系列数据安全问题.所用到的锁就是分布式锁&#xff0c;这种锁需要被多个应用共享才可以&#xff0c;通常使用Redis和zookeeper来实现。 分布式锁有哪些解决方案 常用的三种方案 基于…...

一文讲清数据平台与数据中台的关系与区别

前言 如果您是IT领域或者数据领域的从业者&#xff0c;一定对IT行业“创造”概念的能力深有体会&#xff0c;也一定经常被看起来名称相似&#xff0c;但又不同的各种概念绕的云里雾里&#xff0c;摸不着头脑。今天我们要讨论的是数据平台和数据中台两个概念&#xff0c;您是不…...

Android的Service和Thread的区别

Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。 Android Service是组件&#xff0c;既不能说它是单独的进程也不能说它是单独的线程。 如果非要从通俗的语言层面来理解的话&#xff0c;姑且将其理解为对象。这个Service对象本身作为应用程序的一部分与它的…...

经纬恒润亮相第四届焉知汽车年会,功能安全赋能域控

8月初&#xff0c;第四届焉知汽车年会在上海举行。此次年会围绕当下智能电动汽车的热点和焦点&#xff0c;聚焦于智能汽车场景应用、车载通信、激光雷达、智能座舱、功能安全、电驱动系统等多个领域&#xff0c;汇聚了来自OEM、科技公司、零部件供应商、测试认证机构、政府院校…...

掌握JavaScript单元测试:最佳实践与技术指南

单元测试是软件开发过程中的关键环节&#xff0c;它帮助开发者确保代码的每个独立部分按预期工作。在JavaScript开发中&#xff0c;进行单元测试不仅可以提高代码质量&#xff0c;还可以加快开发速度&#xff0c;因为它们为代码更改提供了安全网。本文将详细介绍如何使用JavaSc…...

spring boot 古茶树管理系统---附源码19810

目 录 摘要 1 绪论 1.1 研究背景 1.2国内外研究现状 1.3论文结构与章节安排 2古茶树管理系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2经济可行性分析 2.1.3操作可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 …...

00067期 matlab中的asv文件

今天在编写代码的过程中&#xff0c;发现自动生成.m文件的同名文件.asv&#xff0c;特此发出疑问&#xff1f;下面是解答&#xff1a; 有时在存放m文件的文件夹中会出现*.asv   asv 就是auto save的意思&#xff0c;*.asv文件的内容和相应的*.m文件内容一样&#xff0c;用记…...

JMeter高效管理测试数据-参数化

文章目录 1.什么是参数化2.定义变量3.CSV数据文件设置 1.什么是参数化 在JMeter中&#xff0c;参数化是一种常用的技术&#xff0c;用于使测试场景更加灵活和动态。通过参数化&#xff0c;你可以让JMeter在每次请求中使用不同的值&#xff0c;这在模拟真实用户行为或测试不同输…...

python学习之writelines

在Python中&#xff0c;writelines() 是一个方法&#xff0c;它属于文件对象&#xff0c;用于将字符串列表写入到文件中。这个方法接受一个序列&#xff08;如列表或元组&#xff09;作为参数&#xff0c;序列中的每个元素都是要写入的一行文本。 ### 函数定义&#xff1a; p…...

STM32学习笔记13-FLASH闪存

FLASH简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&#xff0c;通过闪存存储器接口&#xff08;外设&#xff09;可以对程序存储器和选项字节进行擦除和编程读写FLASH的用途&#xff1a; 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 通过在…...

UIButton的UIEdgeInsetsMake属性(setTitleEdgeInsets,setImageEdgeInsets)

一.UIEdgeInsetsMake的四个属性 UIEdgeInsetsMake 有四个属性,依次是 Top,left,bottom,right [Btn setTitleEdgeInsets:UIEdgeInsetsMake( top, left, bottom, right)]; 四个属性的默认值为0,拿其中一个left属性来聊, 你可以理解为文字距离Btn左边界的“位移”是0, 如果…...

子网掩码是什么?

子网掩码&#xff08;Subnet Mask&#xff09;是用于划分网络的一个32位的二进制数&#xff0c;用于指示IP地址中哪些位用于网络标识&#xff0c;哪些位用于主机标识。 在IPv4网络中&#xff0c;IP地址由32位二进制数组成&#xff0c;通常表示为四个十进制数&#xff0c;每个数…...

SQLALchemy 数据的 CRUD 操作

SQLALchemy 数据的 CRUD 操作 导入必要的模块创建数据库引擎创建会话CRUD 操作创建(Create)读取(Read)更新(Update)删除(Delete)过滤条件使用 `filter` 方法使用 `filter_by` 方法总结聚合函数使用ORM接口使用SQL表达式语言注意关闭会话注意事项SQLAlchemy 是一个流行的…...

reactFiberLane

Lane (车道模型) 英文单词lane翻译成中文表示"车道, 航道"的意思, 所以很多文章都将Lanes模型称为车道模型 Lane模型的源码在ReactFiberLane.js, 源码中大量使用了位运算(有关位运算的讲解, 首先引入作者对Lane的解释(相应的 pr), 这里简单概括如下: Lane类型被定义…...