【Linux】Linux管道揭秘:匿名管道如何连接进程世界

🌈个人主页:Yui_
🌈Linux专栏:Linux
🌈C语言笔记专栏:C语言笔记
🌈数据结构专栏:数据结构
🌈C++专栏:C++

文章目录

  • 1.什么是管道 ?
  • 2. 管道的类型
    • 2.1 匿名管道
      • 2.1.1 介绍pipe()
      • 2.1.2 pipe()简单示例:父子进程通过管道通信
      • 2.1.3 管道的4种情况与5种特性
      • 2.1.4 匿名管道原理
      • 2.1.5 用fork来共享管道的原理
      • 2.1.6 站在文件描述符角度-深度理解管道
      • 2.1.7 站在内核角度-管道的本质
  • 3. 匿名管道总结

1.什么是管道 ?

管道(Pipe)是一种常见的进程间通信(IPC,Inter-Process Communication)机制,在 Unix/Linux 系统中尤其重要。它允许一个进程的输出直接作为另一个进程的输入,而不需要使用中间文件。管道通常用于将多个命令连接起来,让它们像流水线一样处理数据。
管道在 Unix/Linux 系统中提供了一种简便的机制,允许数据在不同进程之间传递。它提供了一个缓冲区,数据写入管道的一端(写端),然后可以从另一端(读端)读取。管道的本质是一种半双工的通信机制,即数据只能沿一个方向流动。
提问:有没有一些直观的管道的利用?
当然。其实早在Linux的指令学习中,我们就已经接触到了管道。就是这个符号|

ubuntu@VM-20-9-ubuntu:~/pipeTest$ ls -l
total 24
-rwxrwxr-x 1 ubuntu ubuntu 16576 Nov  5 11:41 a.out
-rw-rw-r-- 1 ubuntu ubuntu  1285 Nov  5 11:40 pipeTest1.c
ubuntu@VM-20-9-ubuntu:~/pipeTest$ ls -l|grep "pipeTest1.c"
-rw-rw-r-- 1 ubuntu ubuntu  1285 Nov  5 11:40 pipeTest1.c
ubuntu@VM-20-9-ubuntu:~/pipeTest$ 

这就是一个管道的简单使用,我们都知道,在大部分Linux的指令都是一个可执行文件,运行起来就是一个进程。ls -l的作用就是显示当前目录文件的信息,现在我们通过|将这个显示的信息通过管道传递给grep,不就实现了两个进程间的相互通信了嘛。这就是管道的核心作用:实现进程间的通信,高效传递数据,避免了使用临时文件的麻烦.

2. 管道的类型

管道存在两种类型:

  1. 匿名管道,用于父子进程或者兄弟进程间的数据传递,没有名字,仅限具有亲缘关系的进程。
  2. 命名进程,具有文件名,可以在不相干的进程间使用。

2.1 匿名管道

匿名管道通过pipe()创建。

2.1.1 介绍pipe()

#include <unistd.h>
int pipe(int pipefd[2]);

pipefd:是一个数组,它包含两个元素,分别是管道的读端和写端的文件描述符。

  • pipefd[0]:读端(用于读取数据)。
  • pipefd[1]:写端(用于写入数据)。
    pipe()创建一个管道,并将两个文件描述符存储在pipefd数组中。管道的数据流是单向的:数据从写端流向读端。
    关于返回值
  • 成功:返回0.
  • 失败:返回-1.
    使用pepe()的基本流程:
  1. 创建管道:调用pipe()函数。
  2. 使用fork()创建一个子进程。
  3. 在父进程关闭写端,使用读端读取数据。
  4. 在子进程中关闭读端,使用写端将数据传输给父进程。

2.1.2 pipe()简单示例:父子进程通过管道通信

//本代码用来测试子进程提供匿名管道将信息传递给父进程 24/11/5
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define SIZE 1024void writer(int wfd)
{char buf[SIZE];const char* str = "hello father,i am child";int count = 1;pid_t id = getpid();while(true){//格式化输入snprintf(buf,sizeof(buf)-1,"message:%s,pid:%d,times:%d",str,id,count);write(wfd,buf,strlen(buf));count+=1;sleep(1);}
}void reader(int rfd)
{char buf[SIZE];while(true){ssize_t n = read(rfd,buf,sizeof(buf)-1);if(n == -1){perror("read");return;}printf("%s\n",buf);}}int main()
{//文件标识符int fd[2];if(pipe(fd) < 0){//errorperror("pipe error");return 1;}pid_t id = fork();if(id<0){perror("fork error");return 1;}else if(id == 0){//child//关闭读端close(fd[0]);writer(fd[1]);exit(1);}//fatherclose(fd[1]);reader(fd[0]);wait(NULL);return 0;
}

运行结果:
运行结果

如此我们我们便实现了父子间的管道通信。
pipe() 是一个非常重要的系统调用,它为进程间通信提供了一个简单而高效的机制。通过管道,多个进程可以协作完成任务,并且避免了中间文件的使用。在父子进程之间的通信,或在处理大量数据时,管道通常是最常用的 IPC 方式之一。

2.1.3 管道的4种情况与5种特性

4种情况:

  1. 管道内部没有数据时且子进程不关闭自己的写端文件fd,读端(父)就会堵塞等待,直到pipe有数据,
  2. 管道内部被写满且父进程(读端)不关闭自己的fd,写端写满后,就会堵塞等待。
  3. 对于写端而言:不写了且关闭了pipe,读端会将pipe中的数据读完,最后就会读到返回值为0,表示读结束,类似读到了文件的结尾。
  4. 读端不读且关闭,写再写,OS会直接终结写入的进程(子进程)通过信号13)SIGPIPE来杀死进程。
    5种特性:
  5. 自带同步机制。
  6. 血缘关系进行通信,常见于父子进程。
  7. pipe是面向字节流的。
  8. 父子进程退出,管道自动释放,文件的生命周期是跟随进程的。
  9. 管道只能单向通信,半双工的一种特殊情况。

2.1.4 匿名管道原理

通过父子进程继承关系,再将文件描述符关闭,实现一端写,一端读就是匿名管道.
创建匿名管道的步骤:

  1. 父进程以读写的方式打开,文件。父进程fork创建子进程,子进程会拷贝一份PCB结构,PCB中会包含files_struct结构,files_struct中有一个指向struct file(文件)的指针数组,而文件描述符就是这个数组的下标。
  2. 拷贝完成后,子进程也就存在了指向struct file的对应文件描述符。
  3. 又因为,struct file是独属于的文件的,和进程没有关系,也就不用拷贝,也就是说此时父子进程同时指向了一块公共区域struct file(不同进程看见同一份资源)。
  4. write是系统调用接口,会将数据放在内核缓冲区,底层会定期刷新缓冲区将内容写入磁盘。
  5. 匿名管道是一个半双工的通信机制,也就是说,数据只能沿一个方向流动,为了实现半双工的通信方式,父子进程需要关闭各种不需要的文件描述符。

2.1.5 用fork来共享管道的原理

使用fork后
fork

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

0 1 2 分别为 标准输入,标准输出,标准错误
文件描述符

2.1.7 站在内核角度-管道的本质

Linux下一切皆文件.
所以我们也应该用看待文件的眼观,去理解管道。
我们可以将管道(Pipe)理解为一种特殊类型的文件。实际上,管道确实是由操作系统内部的内存缓冲区实现的,它通过文件描述符来进行访问,就像其他普通文件一样。通过这种类比,我们可以从文件的角度理解管道。
内核角度

3. 匿名管道总结

通过匿名管道,进程可以轻松地进行数据交换,而不需要借助临时文件或其他外部资源。尽管管道有一些局限性(如单向传输和缓冲区限制),它仍然是许多进程间通信场景中常见的选择。
注意:管道是半双工的,数据只能向一个方向流动,需要双方通信时,可以建立两个管道。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习Day13 CSS盒子的定位(固定定位篇“附练习”)

一、固定定位 固定定位 &#xff08;position:fixed&#xff09;其实是绝对定位的子类别&#xff0c;一个设置了 position:fixed 的元素是相对于视窗固定的&#xff0c;就算页面文档发生了滚动&#xff0c;它也会一直待在相同的地方。 ⚠️&#xff1a;固定定位会脱离文档流。…

Linux云计算 |【第五阶段】CLOUD-DAY9

主要内容&#xff1a; Metrics资源利用率监控、存储卷管理&#xff08;临时卷ConfitMap、EmptyDir、持久卷HostPath、NFS(PV/PVC)&#xff09; 一、Metrics介绍 metrics是一个监控系统资源使用的插件&#xff0c;可以监控Node节点上的CPU、内存的使用率&#xff0c;或Pod对资…

BM25:最佳匹配 ,文本相关性评分算法

目录 BM25:最佳匹配 一、BM25算法原理 二、BM25算法的应用场景 三、BM25算法的举例说明 BM25:最佳匹配 BM25(Best Matching 25)是一种在信息检索领域中广泛使用的文本相关性评分算法。它基于概率模型,考虑了词频(Term Frequency,TF)、逆文档频率(Inverse Documen…

论文阅读笔记:Image Processing GNN: Breaking Rigidity in Super-Resolution

论文阅读笔记&#xff1a;Image Processing GNN: Breaking Rigidity in Super-Resolution 1 背景2 创新点3 方法4 模块4.1 以往SR模型的刚性4.2 图构建4.2.1 度灵活性4.2.2 像素节点灵活性4.2.3 空间灵活性 4.3 图聚合4.4 多尺度图聚合模块MGB4.5 图聚合层GAL 5 效果5.1 和SOTA…

【游戏引擎之路】登神长阶(十二)——DirectX11教程:If you‘re going through hell, keep going!

【游戏引擎之路】登神长阶&#xff08;十二&#xff09;——DirectX11教程&#xff1a;If youre going through hell, keep going! 2024年 5月20日-6月4日&#xff1a;攻克2D物理引擎。 2024年 6月4日-6月13日&#xff1a;攻克《3D数学基础》。 2024年 6月13日-6月20日&#x…

编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用

往期内容 本专栏往期内容&#xff1a; Pinctrl子系统和其主要结构体引入Pinctrl子系统pinctrl_desc结构体进一步介绍Pinctrl子系统中client端设备树相关数据结构介绍和解析inctrl子系统中Pincontroller构造过程驱动分析&#xff1a;imx_pinctrl_soc_info结构体Pinctrl子系统中c…

toolkit二次开发学习之程序集(ProAsmcomp)和装配体组件路径对象(ProAsmcomppath)

程序集ProAsmcomp可以理解为装配体组件对象。 对象ProAssembly是ProSolid的一个实例&#xff0c;并共享相同的声明。因此&#xff0c;ProAssembly对象可以作为适用于装配体的任何ProSolid和ProMdl函数的输入。特别是&#xff0c;因为你可以使用函数ProSolidFeatVisit()来遍历特…

【启程Golang之旅】深入理解 Protocol Buffers 及其应用

如果你是 Go 语言的开发者&#xff0c;理解如何在 Go 中使用 Protobuf&#xff0c;将帮助你大幅提升数据传输的效率&#xff0c;并实现更高性能的系统设计。 本篇文章将深入探讨 Go 语言中使用 Protobuf 的基础知识、常见应用以及最佳实践&#xff0c;带你一步步了解如何在项目…

Intent介绍#1

Intent 它是Android里非常重要的角色&#xff0c;基本上是核心人物。 能做的 startActivity --> 启动activitybroadcastIntent -> BroadcastContext.startService(Intent) Context.bindService(Intent, BindServiceFlags, Executor, ServiceConnection) -> Service…

鸿蒙开发案例:七巧板

【1】引言&#xff08;完整代码在最后面&#xff09; 本文介绍的拖动七巧板游戏是一个简单的益智游戏&#xff0c;用户可以通过拖动和旋转不同形状的七巧板块来完成拼图任务。整个游戏使用鸿蒙Next框架开发&#xff0c;利用其强大的UI构建能力和数据响应机制&#xff0c;实现了…

(61)使用LMS算法估计线性预测器并计算估计误差的MATLAB仿真

文章目录 前言一、仿真说明二、仿真代码三、仿真结果1.LMS自适应滤波器权向量更新曲线2.LMS自适应滤波器算法学习曲线3.期望信号与LMS自适应滤波器输出信号 前言 本文介绍了LMS自适应滤波器对线性预测器系统权系数的估计&#xff0c;进行100次独立实验&#xff0c;计算平均估计…

313页电力集团大数据应用支撑平台技术支撑服务项目技术投标方案

▲关注智慧方案文库&#xff0c;学习9000多份最新解决方案&#xff0c;其中 PPT、WORD超过7000多份 &#xff0c;覆盖智慧城市多数领域的深度知识社区&#xff0c;稳定更新4年&#xff0c;日积月累&#xff0c;更懂行业需求。 313页Word大型电力集团大数据应用支撑平台 技术支…

6款IntelliJ IDEA插件,让Spring和Java开发如虎添翼

文章目录 1、SonarLint2、JRebel for IntelliJ3、SwaggerHub插件4、Lombok插件5、RestfulTool插件6、 Json2Pojo插件7、结论 对于任何Spring Boot开发者来说&#xff0c;两个首要的目标是最大限度地提高工作效率和确保高质量代码。IntelliJ IDEA 是目前最广泛使用的集成开发环境…

标准IO的应用

1、使用这fscanf和fprintf两个函数实现文件的拷贝。 #include<myhead.h> int main(int argc, const char *argv[]) {FILE *fp;if((fpfopen("./1.txt","w"))NULL){perror("fopen");return -1;}int num100;printf("num%d\n",num…

CPU Study - Instructions Fetch

参考来源&#xff1a;《超标量处理器设计》—— 姚永斌 N-Way CPU 取指问题 如果CPU可以在每个周期内同时解码N条指令&#xff0c;则此类CPU为N-Way超标量处理器。 N-Way超标量处理器需要每个周期从I-Cache中至少取得N条指令&#xff0c;这N条指令成为一组Fetch Group。 为了…

蓝桥杯真题——三角回文数(C语言)

问题描述 对于正整数 n, 如果存在正整数 k 使得 n123⋯kk(k1)2n123⋯kk(k1)/2​, 则 n 称为三角数。例如, 66066 是一个三角数, 因为 66066123⋯36366066123⋯363 。 如果一个整数从左到右读出所有数位上的数字, 与从右到左读出所有数位 上的数字是一样的, 则称这个数为回文数…

string模拟实现构造+析构

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 string模拟实现构造 方案1&#xff08;初始化列表的实现&#xff09;&#xff1a; 这…

yolov8涨点系列之Concat模块改进

文章目录 Concat模块修改步骤(1) BiFPN_Concat3模块编辑(2)在__init_.pyconv.py中声明&#xff08;3&#xff09;在task.py中声明yolov8引入BiFPN_Concat3模块yolov8.yamlyolov8.yaml引入C2f_up模块 在YOLOv8中&#xff0c; concat模块主要用于将多个特征图连接在一起。其具体…

基于Spring Boot和Vue的电子商城系统功能设计

基于Spring Boot和Vue的电子商城系统功能设计 该系统是一个基于Spring Boot和Vue框架的电子商城平台&#xff0c;包含前台商城和后台管理系统。系统功能设计包括用户购物体验和管理员管理功能&#xff0c;支持商品的分类展示、收藏、购物车和订单管理等模块。以下是系统功能的简…

【课程总结】day34:多模态大模型之ViT模型、CLIP模型论文阅读理解

前言 在【课程总结】day31&#xff1a;多模态大模型初步了解一文中&#xff0c;我们对多模态大模型的基本原理有了初步了解&#xff0c;本章内容将通过论文阅读理解&#xff0c;更进一步理解多模态大模型中所涉及的 Vit 架构、Transformer在视觉应用的理念以及 Clip图像与文本…