Linux进程间通信——管道(上)

news2024/11/15 17:43:15

目录

前文

一,进程间通信介绍

二,什么是管道?

三,管道的基本原理

3.1 匿名管道

3.2 管道基本原理

四,样例代码

五,管道的读写规则

六,管道的特点

总结


前文

本文主要是讲解一下进程间通信中管道中的主要内容,如基本原理,样例代码以及特点等

一,进程间通信介绍

首先进程间通信指的是不同进程之间传播或交换信息,众所周知,在Linux中每个进程都是相互独立的,这也就导致进程与进程之间独自沟通困难,因此进程与进程想要沟通交流就需要第三方的帮助,也可以看作是进程间沟通的介质,在进程间通信的发展历程中,介质主要以下面三个为主:管道,System V进程间通信,POSIX进程间通信

而进程间通信的目的主要有以下几个

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

而本文主要是讲解一下进程间通信中的管道。

二,什么是管道?

  • 管道是Unix中最古老的进程间通信的形式。

  • 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”

     

    如上,who | wc -l指令就是对管道的一个简单运用,who进程所执行的内容传入管道中,然后wc进程再读取管道中的内容然后完成自身功能,这样两个进程就在不破坏独立性的情况下通过管道看到同一份资源(也就是who指令显示的内容),从而完成进程间通信。

三,管道的基本原理

首先管道主要分为匿名管道和命名管道,而在管道的原理讲解及其样例代码我们都用匿名管道来完成

3.1 匿名管道

首先匿名管道指的是用pipe函数创建的无名管道,其所需头文件及函数原型如下

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

参数

fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码

因此从上面文件描述符数组以及linux下一切皆文件的原则我们可以推出管道也是文件

 

 

3.2 管道基本原理

管道的实现主要是依靠fork来共享管道,其主要流程如下(下面都是站在文件描述符的角度来理解管道):

 1.父进程创建管道

 如上所示,父进程先用pipe函数创建一个管道,fd[0](对应文件描述符表中的3)对应读管道,fd[1](对应文件描述符表中的4)对应写管道

 2.父进程fork出子进程

 如上所示,父进程fork出的子进程继承了父进程的文件描述符表(注意这里是浅拷贝,所以子进程并不会新建管道),因此子进程的fd[0],fd[1]所指向的内容和父进程一致。

3.父子进程各自关闭不需要的fd(这里我们以父进程写入,子进程读取为例,在使用中以使用场景为主,不必拘泥与父写子读)

 如上图,父进程写入,则将fd[0]关闭,子进程读取,则将fd[1]关闭,自此父进程便可以通过管道看到同一份资源,而后也就可以在不破坏进程独立性的情况下进行进程通信

因此其实上面的三步可以看作都是为了让父子进程可以看到同一份资源从而进行通信的通信方案

四,样例代码

管道的基本原理已经讲解完毕,接下来我们按照上面的原理完成样例代码,通过样例代码进行相关实验,从而进一步探索管道的性质特点,样例代码如下所示

#include <iostream>
#include <unistd.h>
#include <cerrno>
#include <string>
#include <cassert>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
using namespace std;

int main()
{
    //1.创建管道
    int mypipe[2]={0};
    int n=pipe(mypipe);
    if(n<0)//创建失败报错返回
    {
        cout<<"pipe error: "<<errno<<":"<<strerror(errno)<<endl;
        return 1;
    }

    cout<<"mypipe[0]: "<<mypipe[0]<<endl;//[0]-0-张嘴读
    cout<<"mypipe[1]: "<<mypipe[1]<<endl;//[1]-1-用笔写

    //2.创建子进程
    pid_t fd=fork();
    assert(fd!=-1);//判断创建是否成功

    //子进程
    if(fd==0)
    {
        //3.父进程写入,子进程读取
        close(mypipe[1]);

        //4.通信
        char buffer[1024];
        while(true)
        {
            int n=read(mypipe[0],buffer,sizeof(buffer)-1);
            
            if(n>0)
            {
                buffer[n]='\0';
                cout<<"我是子进程,父进程给我的讯息是: "<<buffer<<endl;
            }
            
        }

        //退出
        close(mypipe[0]);
        exit(0);

    }

    //父进程
    //3.父进程写入,子进程读取
    close(mypipe[0]);
    
    //4.通信
    const string str=("hello,我是父进程");
    int cur=1;
    char buffer[1024];
    while(true)
    {
        sleep(1);//写入等待一秒

        snprintf(buffer,sizeof(buffer),"%s,计数器:%d,我的pid:%d",str.c_str(),cur++,getpid());
        write(mypipe[1],buffer,strlen(buffer));
        
    }


    close(mypipe[1]);
    return 0;
}

 运行结果如下

 

 

五,管道的读写规则

1.当没有数据可读时,如果对方不发我们只能等待

 如上图,当将写入设置成五秒一写时,读取方在读取完就会停止执行等数据写入

 2.当管道满的时候,就无法继续写入

 如上图所示,在写入方我们持续写入字母a,并且用cur记录写入的a的个数,然后读取方10s读取一次,我们发现在第一次读取前,cur为65536,也就是说应该写入65536个字母a,但实际上我们发现管道满的时候就不在写入了

3.如果关闭了写端,管道数据读取完后,再次读取read就会返回0,说明读取结束

 如上图所示,我们在停止写入后,管道再次读取,read返回值为0,读取结束

4.写端一直写,读端已经关闭,此时写端的行为是无意义的,os不会允许无意义的行为,低效率,浪费资源的事情,因此会杀死写端,会通过信号来终止。

 如图当读端也就是子进程停止读取时,写端也就是父进程直接被os杀死

5.当要写入的数据量不大于管道容量时,linux将保证写入的原子性:当要写入的数据量大于管道容量时,linux将不再保证写入的原子性

也就是说,当写入的数据量小于管道容量,linux可以保证其数据的正确性,否则数据有可能会失真

六,管道的特点

从上面的内容我们可以的的值管道有如下特点

1.单向通信,也就是其数据流只能单向流动

2.管道的本质就是文件,而且又因为fd(文件操作符)的生命周期随进程结束而结束,因此管道的生命周期也随进程结束而结束

3.具有血缘关系的进程都可以用管道进行进程通信,例如爷孙进程,父子进程,兄弟进程.这是因为,他们都有共同祖先,只要共同祖先调用pipe创建管道,则其后代互相都可以进行管道通信

4.管道通信双方的读写次数没有强相关(字节流),也就是说互相不影响,例如上面的子进程想多久读一次都可以,不受管道另一方的限制

5.具有一定协同能力,让读端和写端都按照一定的规则进行通信——自带同步机制(读写规则)

 

总结

如上便是本文所有内容如果对你有所收货,希望来个三连关注

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

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

相关文章

一文告诉你低代码的价值

随着数字化时代的到来&#xff0c;软件开发已经成为企业不可或缺的一部分。然而&#xff0c;传统的软件开发过程往往缓慢而昂贵。由此&#xff0c;低代码开发平台的出现给企业带来了一种新的软件开发方式。在本文中&#xff0c;我们将探讨低代码开发平台的用处和发展史&#xf…

【数据分享】1929-2022年全球站点的逐年平均露点数据(Shp\Excel\12000个站点)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 对于具体到监测站点的气象数据&#xff0c;之前我们分享过1929-2022年全球气象…

centos7.x升级openeuler详细操作教程

本次升级使用工具为苏研提供 1. 升级前准备操作 1.1 注意事项 ● 迁移工具安装在辅助机中&#xff08;不进行系统迁移的机器&#xff09; ● 辅助机至少给迁移工具的安装预留 1.6G 内存空间 ● 安装之前需要关闭防火墙和 SELinux 的特殊要求 ● 工具安装环境需开启工具端口…

论文格式中要求作者加入orcid的链接在名字后边

论文格式中要求作者加入orcid的链接在名字后边&#xff0c;如下图&#xff1a; 使用网上给的各种写法会出现以下问题&#xff1a; &#xff08;1&#xff09;插入位置不合适 &#xff08;2&#xff09;出现一个正方形的框 &#xff08;3&#xff09;所有参考文献带框&#xff…

中国人民大学与加拿大女王大学金融硕士——努力必有回响,加油,金融人!

有付出&#xff0c;就会有收获&#xff1b;有努力&#xff0c;就会有回响。我们为梦想挥汗如雨&#xff0c;我们为未来奋力跋涉。金融领域在职读研的我们&#xff0c;突破了工作、生活等重围&#xff0c;进入到紧张学习的阶段&#xff0c;充分利用有限的时间完成自己蜕变&#…

微前端(micro-app)使用手册

转载请注明出处&#xff0c;点击此处 查看更多精彩内容 micro-app 使用手册 micro-app 是借鉴了 Web Component 的思想&#xff0c;通过 Custom Element 结合自定义的 Shadow Dom&#xff0c;将微前端封装成一个类 Web Component 组件&#xff0c;从而实现微前端的组件化渲染。…

项目集活动—项目集交付阶段活动

项目集交付阶段活动包括协调和管理项目集实际交付所需执行的项目集活动。这些活动包括围绕 变更控制、报告和信息发布所开展的活动&#xff0c;以及围绕成本、采购、质量和风险所开展的活动。 这些活动提供了贯穿整个项目集生命周期的支持活动和流程&#xff0c;旨在提供项目集…

第十三章 Transformer注意力机制

系列文章目录 第一章 AlexNet网络详解 第二章 VGG网络详解 第三章 GoogLeNet网络详解 第四章 ResNet网络详解 第五章 ResNeXt网络详解 第六章 MobileNetv1网络详解 第七章 MobileNetv2网络详解 第八章 MobileNetv3网络详解 第九章 ShuffleNetv1网络详解 第十章…

日志分析篇之Linux日志分析

0x00 前言 Linux系统拥有非常灵活和强大的日志功能&#xff0c;可以保存几乎所有的操作记录&#xff0c;并可以从中检索出我们需要的信息。 本文 简介一下Linux系统日志及日志分析技巧。 0x01 日志简介 日志默认存放位置&#xff1a;/var/log/ 查看日志配置情况&#xff1a;…

抖音本地生活林客服务商开通

抖音林客系统是一种面向本地生活服务的平台&#xff0c;它将消费者与商家联系在一起&#xff0c;在提供更便捷的服务的同时也创造了商业机会。考虑到目前互联网和移动设备的普及程度&#xff0c;以及人们对于生活质量和便利性的不断追求&#xff0c;抖音林客系统具有广阔的市场…

【AUTOSAR】AUTOSAR开发工具链(十)----基于BTC的MIL/SIL测试操作说明(2)

三、PowerWindow demon SIL测试 <一>、如果是手写的纯C代码使用方法如下 创建C代码工程文件 添加C代码的工程文件和不在一个文件夹的头文件路径 选择测试结构 接口参数格式定义 设置采样时间等于调度周期 点击import,添加测试用例类似于MIL测试 <二>、如果是模型…

小航助学2023年6月GESP_C++二级试卷(含题库答题软件账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 单选题2.0分 删除编辑附件图文 答案:D 第1题高级语言编写的程序需要经过以下&#xff08; &#xff09;操作&#xff0c;可以生成在…

这篇文章让你彻底了解什么是安全测试?

目录 前言 安全测试的验证点&#xff1a; 主要归结为以下几点&#xff1a;&#xff08;后期可以优化成一个安全测试的框架结构&#xff09; 总结&#xff1a; 前言 web应用无处不在&#xff0c;存在于每个行业&#xff0c;现在的发展速度非常快速&#xff0c;且web应用在软…

Jetpack Compose实现的一个优雅的 Toast 组件——简单易用~

Toast 是Android中常见的轻量级提示 本文将介绍如何使用Compose技术实现一个Toast组件 不是一个简单的toast 优雅-简洁-动画 才是我的风格 系统原生的Toast默认是在底部弹出&#xff0c;配合kotlin语音的特性&#xff0c;简单封装一下&#xff0c;使用方法非常简洁 inline …

CodeForces..好数列.[简单].[数学规律]

题目描述&#xff1a; 题目解读&#xff1a; 给定n&#xff0c;k 数组a是由0和1组成的&#xff0c;长度为n的数组&#xff0c;数组满足&#xff1a; a的前i个元素中至少有i/k个等于1&#xff1b; a的后i个元素中至少有i/k个等于1&#xff1b; 输入n,k 输出满足条件的数组的…

【JAVA】学生信息管理系统

目录 前言 一、环境搭建 二、功能实现 1.学生信息类的创建 2.学生信息的添加功能 3.学生信息的删除功能 4.学生信息的修改功能 5.学生信息的查看功能 三、主类的调用 1.界面的搭建 2.学生端和教师端 3.系统和功能的选择 总结 前言 JAVA实现的学生信息管理…

8.6 socket套接字及TCP的实现框架

socket套接字 目录 socket套接字 体系结构的两种形式 几种常见的网络编程接口 socket套接字 socket常用API介绍 socket套接字 三元组【IP地址&#xff0c;端口&#xff0c;协议】 地址族结构体 套接字类型 TCP通信的实现过程 体系结构的两种形式 网络的体系结构 (N…

保护云环境:云渗透测试和安全策略探究

随着云计算技术的快速发展&#xff0c;越来越多的组织将他们的数据和应用程序迁移到云端。然而&#xff0c;与此同时&#xff0c;云安全也面临着新的挑战。云渗透测试是一种评估云环境安全性的方法&#xff0c;它帮助组织发现并解决可能存在的漏洞和弱点。在本文中&#xff0c;…

docker - 部署java/python项目

目录 1、docker - 部署 java 项目 1. 创建 mysql 容器 2. 验证mysql&#xff0c;dbserver 连接 mysql &#xff0c;服务器ip:3306 ,账户&#xff1a;root 密码&#xff1a;123456 3. 创建tomcat容器 4. 验证&#xff1a;http://ip:80 5. 开发项目war包&#xff0c;放到to…

【MOOC 作业】第2章 应用层

不是标答也不是参考答案 仅从个人理解出发去做题 1、(20分) 什么是持久性连接&#xff1f;什么是非持久性连接&#xff1f;持久性连接与非持久性连接区别如何&#xff1f; 持久性连接&#xff1a;每个请求/响应对都经同一个 TCP 连接发送。非持久性连接&#xff1a;每个请求/…