<Linux>进程间通信--管道

news2024/9/20 22:54:50

前言😃😃😃

进程间通信的方式

  1. 管道 - Linux原生提供

  1. 2SystemV - 多线程单机通信

  1. posix - 多线程网络通信

这里我们主要是介绍一下管道

一、生活和计算机中的管道😜

生活中的管道特点

  1. 都是有出口入口

  1. 都是单向传输内容的(例如:纯净水管道 和 污水管道 不可能同时传输纯净水和污水对吧)

  1. 管道中传输的都是资源(例如:运输天然气等等)

计算机中的管道:

和生活中的管道特点类似,同样都是有出口和入口的都是单向传输的,不过计算机中传输的资源是“数据”。

总结:管道是一种进程间单向通信的方式。

二、管道实现进程间通信的原理😏

先说核心概念:管道通信背后是通过进程之间的共享内存进行通信的,记住这句话好了,我们开始解说原理。

在说原理之前,我们需要明确一点 --- 进程之间是具有很强的独立性的;

我们需要知道在创建一个进程时,操作系统会为这个进程创建一个task_struct结构体和files_struct文件结构体,task_struct来记录这个进程的信息,files_struct文件结构体来记录这个进程打开的文件信息。这里我们需要知道的是:files_struct是用来记录一个进程打开文件的信息的,OK知道了这一点

在files_struct中有一个fd_array[]数组 -- 用来存放进程打开的文件fd(文件描述符的),在这里我们可以举个实例:我们打开的每一个进程都会自动打开stdin/stdout/stderr -- 分别是标准输入/标准输出/标准错误,对应的在fd_array[0] = 0, fd_array[1] = 1, fd_array[2] = 2(注意:数组下标不一定就是对应的文件描述符,这里只是一个例子)

这里我们需要知道的是:files_struct中有一个fd_array[]数组 -- 用来存放进程打开的文件fd

有了以上的认识之后,我们就可以描述一下一个进程是如何去访问文件的了:

例如进程A想访问一个打开的文件B,A通过它自己的task_struct结构体找到指向files_struct结构体的成员指针,再通过files_struct找到其中的fd_array[]成员数组,访问这个数组从而就可以找到这个进程打开的文件B的文件描述符fd了,通过fd就可以访问这个文件B了。

好了现在又有了一个阶段性的认识,知道了进程是如何访问文件的了,这里很重要的一点,那些是进程相关的数据结构、那些是文件相关的数据结构?

为什么要做这个区分?因为进程之间是有很强的独立性的,有关进程的数据结构之间是基本不可能有什么交集的,就更不要说通过进程的相关数据结构进行进程间通信了。而文件相关的数据结构就不一样,文件要被访问是会被加载在内存中的,而这些被加载到内存中的文件是可以被任何进程访问的!!!这是一个十分关键的一点,管道通信的理解关键就在于此。也就是说我们可以通过两个进程访问一个文件来间接的实现进程间通信。

以上对管道通信的原理做出的相对清楚的解释,还有一点小小细节,为了保证管道的特点,需要多加以下一下规则:

  • 一个进程只用写方式打开文件,另一个文件只用读方式打开文件(保证单向)

三、demo代码😍

如下写了一个使用管道通信的例子:

大致的流程是:

  1. 创建管道

  1. 创建子进程

  1. 做子进程的接收处理

  1. 做父进程的发送处理

这里使用管道通信涉及到了一个系统函数:int pipe(int pipefd[2])

用处是我们传入一个一维数组,他会分别以只w写和只r读的方式打开同一个文件,将只读的文件描述符放入pipefd[0],将只写的文件描述符放入pipefd[1]

其实就是一个简化操作的函数,我们自己以两种方式打开也可以;

简单说一下我们做了什么事情:

(如果是小白)关于头文件的包含和函数我们使用了几个关键函数:fork()、pipe、waitpid(),snprintf()去查相关的man手册即可

这里的代码:

首先通过pipe创建一个管道用pipefd存放,子进程创建一个缓冲区来接收父进程发送的数据。

父进程创建一个缓冲区来存放发送的数据,最后结束等待子进程退出处理。

#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <cassert>

using namespace std;

int main()
{
    // 创建管道
    int pipefd[2] = {0};
    int n = pipe(pipefd); // 创建的pipedfd[0]是读 pipedp[1]是写
    assert(n != -1);
    (void)n;

    // 创建子进程
    pid_t id = fork();
    assert(id >= 0);
    if (id == 0) // 子进程接收处理+关闭写
    {
        close(pipefd[1]);
        // 搞一个缓冲区来接收数据
        while (true)
        {
            char buffer[1024];
            ssize_t s = read(pipefd[0], buffer, sizeof(buffer) - 1);
            buffer[s] = 0;

            cout << getpid() << ":reserve a message from father:" << buffer << endl;
        }
    }
    // 父进程发送处理+关闭读
    close(pipefd[0]);

    char send_Buffer[1024];
    while (true)
    {
        string msg = "儿子我给你发了一个信息";

        snprintf(send_Buffer, sizeof(send_Buffer), "[%d]:%s", getpid(), msg.c_str());
        write(pipefd[1], send_Buffer, strlen(send_Buffer));

        sleep(1);
    }

    //等待子进程退出
    int ret = waitpid(id, nullptr, 0);
    assert(ret > 0);
    (void)ret;

    return 0;
}

四、使用管道不可避免的几个小细节🙋

a.如果写的数据过快,读得慢,缓冲区写满了就不能再写了。

b.如果写的慢,读的块,管道没有数据的时候,读必须等待。

c.写的文件关闭了,读的时候返回0,表示读到了文件结尾。

d.读的文件关闭了,写继续写,操作系统(OS)会终止写进程。

如上四点大家可以自己实践

ab两点可换一种说法即 -- 管道是具有访问控制的,显示器也是一个文件,父子同时往显示器上写入的时候,没有说一个会等待另一个的情况,也就是缺乏访问控制。

五、管道的使用总结😰

  1. 管道一般用于父子间通信。

  1. 管道具有通过进程间协同,提供的访问控制。

  1. 管道提供的是面向流式的通信服务 -- 字节流。

  1. 管道是基于文件的,文件的生命周期是随进程的,管道也是。

  1. 管道是单向通信的,是半双工的一种特殊情况。

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

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

相关文章

雨水情测报设施包含哪些设备?

通常雨水情测报及大坝安全监测设施&#xff0c;主要包括&#xff1a;大坝安全监测终端、雨水情监测终端、GNSS监测站、雷达水位计、大坝安全监测平台、雨水情测报系统平台等产品。雨水情测报及大坝安全监测系统方案解决方案雨水情测报及大坝安全监测系统解决方案&#xff0c;主…

华为OD机试题,用 Java 解【字符串加密】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…

Raft图文详解

Raft图文详解 refer to: Raft lecture (Raft user study) - YouTube Raft PDF Raft算法详解 - 知乎 (zhihu.com) 今天来详细介绍一下Raft协议 Raft是来解决公式问题的协议&#xff0c;那么什么是共识呢&#xff1f; 在分布式系统里面&#xff0c;consensus指的是多个节点对…

UEFI移植LVGL

自己组装过游戏主机的应该都有看到过&#xff0c;进入BIOS设置&#xff0c;酷炫的界面便呈现在眼前&#xff0c;而很多BIOS&#xff0c;使用的还是标准的界面。现在有个趋势&#xff0c;phoenix和insyde也在慢慢朝这种GUI界面发展&#xff0c;而AMI的使用C编写的界面已经非常完…

spring学习3.5

Bean是什么 Spring里面的Bean就类似是定义的一个组件&#xff0c;而这个组件的作用就是实现某个功能的&#xff0c;这里所定义的Bean就相当于给了你一个更为简便的方法来调用这个组件去实现你要完成的功能。 IoC是什么 谁控制谁&#xff0c;控制什么&#xff1f; 传统Java SE程…

11.SpringSecurity基于JWT实现Token的处理

SpringSecurity基于JWT实现Token的处理 前面介绍了手写单点登录和JWT的应用&#xff0c;本文结合SpringSecurity来介绍下在SpringBoot项目中基于SpringSecurity作为认证授权框架的情况下如何整合JWT来实现Token的处理。 一、认证思路分析 SpringSecurity主要是通过过滤器来实现…

【JavaWeb】从输入URL到展示出页面的过程

目录 DNS域名解析 检查hosts文件 查询缓存 查询本地DNS服务器 ​编辑查询根域名服务器等 三次握手建立连接 发送请求 响应请求 页面渲染 断开连接 这些过程简单的理解为先找到某人地址&#xff0c;给他发送消息可以去他家拿东西吗&#xff1f;他同意后拿到他的东西在…

33- PyTorch实现分类和线性回归 (PyTorch系列) (深度学习)

知识要点 pytorch最常见的创建模型的方式, 子类 读取数据: data pd.read_csv(./dataset/credit-a.csv, headerNone) 数据转换为tensor: X torch.from_numpy(X.values).type(torch.FloatTensor) 创建简单模型: from torch import nn model nn.Sequential(nn.Linear(15, 1…

Dockerfile简单使用入门

什么是 Dockerfile&#xff1f; Dockerfile 是一个用来构建镜像的文本文件&#xff0c;文本内容包含了一条条构建镜像所需的指令和说明。 docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。 例如&#xff1…

亚马逊电动水泵UL778测试报告

电动水泵UL778如何办理&#xff1f; 近期亚马逊在3C品类吹的风可够大的&#xff0c;严查起UL测试报告了。许多卖家反映收到相关邮件通知&#xff0c;产品也由于在规定时间内无法提供UL测试报告&#xff0c;出现被暂停销售、listing被下架等问题。 从亚马逊此次的动作来看&…

深度学习卷积神经网络CNN之 VGGNet模型主vgg16和vgg19网络模型详解说明(理论篇)

1.VGG背景 2. VGGNet模型结构 3. 特点&#xff08;创新、优缺点及新知识点&#xff09; 一、VGG背景 VGGNet是2014年ILSVRC&#xff08;ImageNet Large Scale Visual Recognition Challenge大规模视觉识别挑战赛&#xff09;竞赛的第二名&#xff0c;解决ImageNet中的1000类图…

Padloc:一个直观的开源密码管理器

让我们了解一下这个具有令人愉悦的用户界面、跨平台可用的开源密码管理器。有大量适用于个人和团队的免费的和收费的密码管理器。然而&#xff0c;当谈到开源方案时&#xff0c;它通常仅限于几个好的方案&#xff0c;如 Seahorse、KeePassXC 和 Bitwarden。如果你已阅读过我们的…

【浅学Java】InnoDB存储引擎下MVCC(多版本并发控制 )

TOC 1. MVCC是什么 MVCC是面试中比较常见的一个问题&#xff0c;那么什么是MVCC机制&#xff0c;它的作用是什么&#xff1f; 它的英文全称是 Multi-Version Concurrency Control &#xff0c;也就是“多版本并发控制”的意思。在MySQL InnoDB存储引擎下&#xff0c;RC、RR就…

DBeaver 超级详细的安装与使用

一、下载DBeaver DBeaver是一种通用数据库管理工具&#xff0c;适用于需要以专业方式使用数据的每个人&#xff1b;适用于开发人员&#xff0c;数据库管理员&#xff0c;分析师和所有需要使用数据库的人员的免费(DBeaver Community) 的多平台数据库工具。 DBeaver支持80多个数据…

Redis学习(四):三种特殊类型及常用操作

geospatial &#xff08;地理位置&#xff09; 查询经纬度网站 添加位置GEOADD 两极无法直接添加&#xff0c;我们一般会下载城市数据&#xff0c;通过java程序导入 可以看到这个命令也支持一次性添加多个。 获取位置GEOPOS 获取两点之间距离 GEODIST 默认单位是m&#xff0c…

MySQL面试题-锁相关

目录 1.MySQL 锁的类型有哪些呢&#xff1f; 2.如何使用全局锁 3.如果要全库只读&#xff0c;为什么不使用set global readonlytrue的方式&#xff1f; 4.表级锁和行级锁有什么区别&#xff1f; 5.行级锁的使用有什么注意事项&#xff1f; 6.InnoDB 有哪几类行锁&#xff…

上海亚商投顾:沪指震荡调整 酒店等消费股逆势活跃

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。市场情绪沪指今日震荡盘整&#xff0c;创业板指V型反弹&#xff0c;上证50跌超1%&#xff0c;保险、银行、券商等金融股下挫。…

Peppol的发展史和基本框架

Peppol&#xff08;Pan-European Public Procurement Online&#xff09;是欧洲区域内的一个跨境公共采购电子商务平台试点项目&#xff0c;由欧盟委员会和Peppol联盟成员国共同资助建立&#xff0c;旨在通过制定标准化框架&#xff0c;推动欧盟成员国在公共采购相关的电子目录…

如何优化棋牌游戏服务器网络带宽

随着在线棋牌游戏的普及&#xff0c;如何提升游戏服务器的性能成为了一个重要的话题。高性能的独立服务器可以保证游戏的稳定性和流畅度&#xff0c;提高玩家的游戏体验&#xff0c;从而带来更多的收益。其中&#xff0c;优化网络带宽是保证棋牌游戏服务器稳定性和流畅度的关键…

给大家介绍几个数据分析,数据可视化的网站合集

对于初学者和进阶者准备了10让人眼前一亮的网站&#xff0c;可以说是很全了&#xff0c;建议收藏~ 一、数据来源 1、艾瑞数据 http://index.iresearch.com.cn/ 该网站免费公开的部分可以提供一些简单的APP使用数据以及人群、区域等分析。 2、CNNIC中国互联网络信息中心 http…