管道-匿名管道

news2025/1/13 9:26:47

一、管道介绍 

        管道(Pipe)是一种在UNIX和类UNIX系统中用于进程间通信的机制。它允许一个进程的输出直接成为另一个进程的输入,从而实现数据的流动。管道是一种轻量级的通信方式,用于协调不同进程的工作。

      1. 创建和使用管道:

  • 创建: 管道可以通过在Shell命令中使用竖线符号 | 来创建,也可以在程序中使用系统调用 pipe 来创建。
  • 使用: 管道通过将一个进程的标准输出(stdout)连接到另一个进程的标准输入(stdin),从而实现两者之间的数据传输。
  • 2. 匿名管道:
  • 类型: 管道分为匿名管道(Anonymous Pipe)和命名管道(Named Pipe)。
  • 匿名管道: 由操作系统动态创建,用于具有亲缘关系的进程之间的通信,其句柄仅在创建时有效。
  • 3. 命名管道(FIFO):
  • 类型: 命名管道是一种特殊的文件,也称为FIFO(First In, First Out)。
  • 命名: 在文件系统中具有唯一名称,不限于亲缘关系的进程,可以在不同进程之间共享数据。
  • 4. 进程间通信(IPC):
  • 目的: 管道用于实现进程间通信,允许一个进程的输出成为另一个进程的输入。
  • 特点: 管道是半双工的,数据流只能单向传输,需要两个管道来实现双向通信。
  • 5. Shell中的管道:
  • 语法: 在Shell中,使用 | 将一个命令的输出传递给另一个命令,形成管道。
  • 示例: ls | grep "pattern",这会将 ls 的输出传递给 grep 进行过滤。
  • 6. 程序中的管道:
  • 系统调用: 在C语言等编程语言中,可以使用 pipe 系统调用创建管道,使用 dup2 复制文件描述符,最后使用 exec 执行其他程序。
  • 7.关闭和错误处理:
  • 关闭: 使用管道时,需要确保在合适的时候关闭不需要的文件描述符,以避免资源泄漏。
  • 错误处理: 对于管道的创建和使用,需要进行错误处理,以处理可能发生的异常情况。
  • 8.限制和注意事项:
  • 有限性: 管道的缓冲区有限,可能导致阻塞,特别是在没有足够空间来容纳数据时。
  • 同步问题: 管道的使用可能涉及到进程间的同步问题,需要谨慎处理。
图1  匿名管道
ls |wc -l

        这是一种典型的使用匿名管道的情况,用于连接两个进程,其中一个进程的输出成为另一个进程的输入。在这里,ls命令用于列出目录中的文件,而wc -l命令则用于统计行数,因此可以用于统计目录中文件的数量。

 二 、管道特点

 

匿名管道工作

  1. 内核内存中的缓冲器:

    • 管道是在内核内存中维护的缓冲器,用于在两个进程之间传递数据。这个缓冲器是有限的,因此管道的容量是有限的,当管道达到容量上限时,写操作可能会阻塞。
  2. 匿名管道与有名管道的特性:

    • 匿名管道没有文件实体,它是通过系统调用 pipe 创建的。有名管道则是在文件系统中有唯一名称的文件,通过 mkfifo 创建。有名管道可用于不同进程之间的通信,而匿名管道通常用于有亲缘关系的进程。
  3. 管道的读写操作:

    • 管道的读写操作与文件相似,可以使用标准的文件I/O操作,如readwrite。进程通过向管道写入数据,或从管道读取数据来进行通信。
  4. 消息边界的缺失:

    • 与消息队列不同,管道是一个字节流,不存在消息边界的概念。进程可以读取任意大小的数据块,而不受写入数据块大小的限制。这种特性使得管道在流式数据传输场景中非常灵活。
  5. 数据的顺序性:

    • 管道传递的数据是顺序的,即数据的读取顺序与写入顺序保持一致。这确保了在管道中传递的数据在接收端是按照正确的顺序被处理。
  6. 单向传递:

    • 管道是单向的,即数据的传递方向是确定的。一端用于写入数据,另一端用于读取数据。这使得管道成为半双工的通信机制。
  7. 一次性读取:

    • 从管道中读取数据是一次性的操作,即一旦数据被读取,它就从管道中被移除。这也意味着,如果某个进程没有读取所有写入管道的数据,这些数据将被丢弃。
  8. 无法随机访问:

    • 与文件不同,管道中的数据不能通过 seek() 等操作进行随机访问。由于管道是一个流式的通信机制,数据只能按顺序读取。
  9. 匿名管道的限制:

    • 匿名管道通常限制在具有公共祖先的进程之间使用。这通常是父子进程之间的通信,或者通过其他方式具有亲缘关系的进程之间的通信。匿名管道是在 pipe() 系统调用时创建的。

三、 为什么可以使用管道进行进程间通信

 

        在父子进程或兄弟进程之间使用匿名管道进行通信时,理解文件描述符表的概念是非常重要的。文件描述符表是每个进程内部维护的一张表,用于跟踪打开的文件和其他I/O资源。以下是匿名管道在进程间通信中与文件描述符表的关系:

  1. 文件描述符的创建:

    • 当调用 pipe 系统调用创建匿名管道时,会返回两个文件描述符,这两个文件描述符分别代表管道的读端和写端。
  2. 父子进程之间的文件描述符继承:

    • 在调用 fork 创建子进程时,子进程将会继承父进程的文件描述符表。这意味着子进程也会获得父进程的管道文件描述符。
  3. 关闭不需要的文件描述符:

    • 通常,在使用管道进行通信时,需要关闭不需要的文件描述符。例如,在子进程中关闭管道的写端,在父进程中关闭管道的读端,以确保每个进程只使用它需要的文件描述符。
  4. 数据流动:

    • 当一个进程向管道写入数据时,数据通过管道流向另一个进程。这是通过在一个进程中使用 write,在另一个进程中使用 read 来完成的,而这些操作使用文件描述符。
匿名管道通信(父子进程、兄弟进程)

四、管道的数据结构

 

五、 父子进程之间使用匿名管道通信


/*
            #include <unistd.h>
            int pipe(int pipefd[2]);
                功能:
                    创建一个匿名管道,用来进程通信
                参数:
                    int pipefd[2] 这个数组是一个传出参数
                    pipefd[0] 对应管道的读端(文件描述符)
                    pipefd[2] 对应管道的写端
                返回值:
                    成功:0
                    失败:-1
                注意: 匿名管道只能用于具有关系的进程之间的通信(父子进程、兄弟进程)

 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
// 子进程发送数据给父进程,父进程输出
int main(){
    // 在fork之前创建管道
    int pipefd[2];
    int ret = pipe(pipefd);
    if(ret==-1){
        perror("pipe");
        exit(0);
    }
    // 创建子进程
    pid_t pid =fork();
    if(pid>0){
        printf(" i am a parent,pid : %d\n",getpid());
        char buf[1024]={0};
        while(1){
            //读
            int len = read(pipefd[0],buf,sizeof(buf));
            printf("parent recv :%s,pid: %d\n",buf,getpid());

            char * str ="heloo ,i am your parent";
            // 想管道写数据
            write(pipefd[1],str, strlen(str));
            sleep(1);
        }

    }else if(pid==0){
        //sleep(10);
        printf(" i am a child process, pid: %d\n",getpid());
        char buf[1024]={0};
        while (1){
            char * str ="heloo ,i am your grandfaher";
            // 向管道写数据
            write(pipefd[1],str, strlen(str));
            sleep(1);
            // 读
            int len = read(pipefd[0],buf,sizeof(buf));
            printf("parent recv :%s,pid: %d\n",buf,getpid());


        }

    }
    return 0;
}

 六、fpathconf查看管道大小

  fpathconf 是一个用于获取文件路径配置值(pathconf values)的函数。通过这个函数,可以获取与文件或文件描述符相关联的一些运行时配置信息,包括管道的大小。

       要查看管道的大小,可以通过 fpathconf 函数来获取相应的配置值。对于管道的大小,我们关注的是 PIPE_BUF,它表示一个原子的写入或读取操作的最大字节数。注意,PIPE_BUF 并不一定反映实际管道的大小,而是表示每次写入或读取的最大字节数,它是一个限制,不同系统可能有不同的值

 

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

int main(){
    int pipefd[2];

    int ret = pipe(pipefd);
    //获取管道大小
    long size = fpathconf(pipefd[0],_PC_PIPE_BUF);
    printf("pipe size : %ld\n",size);
    return 0;
}

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

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

相关文章

Docker Alist 在线网盘部署

文章目录 拉取镜像创建并运行查看容器自动生成的密码在浏览器中进行访问 挂载本地磁盘 拉取镜像 docker pull xhofe/alist-aria2创建并运行 # -v /data/alist:/opt/alist/data 挂载本地目录 docker run -d --restartalways -v /data/alist:/opt/alist/data -p 5244:5244 -e P…

国庆作业6

TCP服务器 #include "head.h" #define PORT 2580 //端口号 #define IP "192.168.31.219" //本机IP int main(int argc, const char *argv[]) {sqlite3* dbNULL;if(sqlite3_open("./my.db",&db)!SQLITE_OK){fprintf(stde…

FFmpeg 命令:从入门到精通 | ffmpeg filter(过滤器 / 滤镜)

FFmpeg 命令&#xff1a;从入门到精通 | ffmpeg filter&#xff08;过滤器 / 滤镜&#xff09; FFmpeg 命令&#xff1a;从入门到精通 | ffmpeg filter&#xff08;过滤器 / 滤镜&#xff09;ffmpeg fliter 基本内置变量视频裁剪文字水印图片水印画中画视频多宫格处理 FFmpeg 命…

BIOS 如何确定引导扇区的位置

机械硬盘的信息都是存储在磁盘的表面&#xff0c;他们是由一圈一圈的磁道组成的。以前的磁盘的不同磁道的扇区数量是相同的&#xff0c;这就导致了很大的浪费&#xff0c;因为最外面的磁道的密度是最低的&#xff0c;信息是最安全的&#xff0c;所以最外面的磁道是0磁道。后来由…

NPDP产品经理知识(产品创新管理)

复习文化&#xff0c;团队与领导力 产品创新管理&#xff1a; 如何树立愿景&#xff1a; 如何实现产品战略 计划 实施产品开发&#xff1a; 商业化&#xff0c;营销计划&#xff0c;推广活动 管理产品生命周期&#xff1a; 新式走向市场的流程&#xff1a;

win10 关闭病毒防护

windows10彻底关闭Windows Defender的4种方法 - 知乎

科技+智慧+颜值,智慧公厕黑科技提升城市形象

现代社会的科技和智慧正以惊人的速度渗透到我们生活的各个方面&#xff0c;包括公共设施。而作为城市形象的重要组成部分之一&#xff0c;公厕也在不断创新中迎来了智慧的时代。 在传统的公厕中&#xff0c;一些问题一直困扰着我们&#xff0c;比如厕位的占用情况、空气质量的…

腾讯云域名API解析升级版本(通过Java实现)腾讯云动态公网IP绑定域名实现内网服务器公网穿透

公众号推广: 目前CSDN进行VIP可见,文章可在微信公众号进行免费的阅读。 文章内容经过认证实践,比较的清晰易懂,适合初次接触的人员。 请关注微信公众号:菜鸟编程踩坑之路,进入公众号搜索关键词 内网穿透 需求场景: 首先我自己组装了一台自己的服务器,相比较购买的阿…

微信小程序——CSS3渐变

SS3 渐变&#xff08;gradients&#xff09;可以在两个或多个指定的颜色之间显示平稳的过渡。CSS3 定义了两种类型的渐变&#xff08;gradients&#xff09;&#xff1a; 说明 1、线性渐变&#xff08;Linear Gradients&#xff09;- 向下/向上/向左/向右/对角方向&#xff1…

基于体素场景的摄像机穿模处理

基于上一篇一种基于体素的射线检测 使用射线处理第三人称摄像头穿模问题 基于体素的第三人称摄像机拉近简单处理 摄像机移动至碰撞点处 简单的从角色身上发射一条射线到摄像机&#xff0c;中途遇到碰撞就把摄像机移动至该碰撞点 public void UpdateDistance(float defaultDist…

机器学习(监督学习)笔记

笔记内容 代码部分 # 实验2-1 # 批梯度下降 import pandas as pd import numpy as np import random as rd import matplotlib.pyplot as plt # load dataset df pd.read_csv(temperature_dataset.csv) data np.array(df) y0 np.array([i[0] for i in data]) # 第一列作为…

Docker项目部署

目录 一、前端项目部署 1、上传文件 2、开启容器 3、测试 二、后端项目部署 1、打包java项目 2、将jar包和Dockerfile文件长传到Linux系统 3、构建镜像 4、开启容器 5、测试 一、前端项目部署 1、上传文件 里面包括页面和配置文件 worker_processes 1;events {worker…

云畅科技TMS解决方案助力华菱线缆实现智能货运管理

9月26日下午&#xff0c;湖南华菱线缆股份有限公司TMS物流系统上线启动会成功举办&#xff0c;由云畅科技倾力打造的华菱线缆TMS物流系统正式上线运行&#xff0c;标志着湖南华菱线缆股份有限公司在智能化物流货运管理领域的一次重大突破。 湖南华菱线缆股份有限公司董事兼总经…

C#捕捉全局异常

1.运行图片 2.源码 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms;namespace 捕捉全局异常 {internal static class Program{/// <summary>/// 应用程序的主入口点。/// </summary…

竞赛选题 机器视觉opencv答题卡识别系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 答题卡识别系统 - opencv python 图像识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分…

【Spring】更简单的读取和存储对象

更简单的读取和存储对象 一. 存储 Bean 对象1. 前置工作&#xff1a;配置扫描路径2. 添加注解存储 Bean 对象Controller&#xff08;控制器存储&#xff09;Service&#xff08;服务存储&#xff09;Repository&#xff08;仓库存储&#xff09;Component&#xff08;组件存储&…

基于transformer的心脑血管心脏病疾病预测

视频讲解:基于transformer的心脑血管疾病预测 完整数据代码分享_哔哩哔哩_bilibili 数据展示: 完整代码: # pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple/ # pip install optuna -i https://pypi.tuna.tsinghua.edu.cn/simple/ import numpy as np …

C++ - 位图 - bitset 容器介绍

前言 之前的两篇博客已经完成 闭散列的开放地址法的哈希表 和 哈希桶基本实现&#xff0c;和对 unordered_set 和 unordered_map 的封装 &#xff1a;C - 封装 unordered_set 和 unordered_map - 哈希桶的迭代器实现_chihiro1122的博客-CSDN博客C - 开散列的拉链法&#xff08…

【JVM】运行时数据区(内存区域划分)详解

文章目录 前言一、JVM 运行时数据区1, 堆2, Java 虚拟机栈3, 本地方法栈4, 程序计数器5, 元数据区 / 方法区 二、内存异常问题1, 栈溢出2, 内存溢出3, 内存泄露 总结 前言 &#x1f4d5;各位读者好, 我是小陈, 这是我的个人主页 &#x1f4d7;小陈还在持续努力学习编程, 努力通…

【重拾C语言】三、分支程序设计(双分支和单分支程序设计、逻辑判断、多分支程序设计、枚举类型表示;典型例题:判断闰年和求一元二次方程根)

目录 前言 三、分支程序设计 3.1 判断成绩是否及格——双分支程序设计 3.2 成绩加上获奖信息—单分支程序设计 3.3 逻辑判断——布尔类型 3.4 获奖分等级——多分支程序设计 3.5 表示汽车种类——枚举类型 3.6 例题 3.6.1 例题——判断某个年份是否闰年 3.6.2 例题—…