【Linux】进程间通信 -- 管道

目录

  • 一. 管道
    • 1. 匿名管道
      • 1.1. 匿名管道的创建
        • 命令行创建
        • pipe() 函数创建
      • 1.2 匿名管道的读写规则
      • 1.3 匿名管道的特点
    • 2. 命名管道
      • 2.1 命名管道的创建
        • 命令行创建
        • mkfifo() 函数创建
      • 2.2 命名管道的读写规则和特点

进程间通信 (Inter-Process Communication, 简称 IPC) 是多进程协作的基础, 当进程之间需要交互, 协同完成一件事时, 就需要进程通信.

进程间通信的目的:

  • 数据传输: 不同进程间进行数据传输.
  • 资源共享: 多个进程之间需要共享资源.
  • 事件通知: 一个进程向其他进程发送消息, 通知处理相关事件.
  • 进程控制: 有些进程希望完全控制另一个进程的执行, 此时控制进程希望能够拦截另一个进程的所有陷阱和异常, 并能够及时知道它的状态改变.

由于进程之间是相互独立的, 所以需要操作系统提供一份公共的空间或资源, 使得进程可以从公共空间或资源读写数据, 所以进程通信的本质是 操作系统提供一份不同的进程都可以访问的资源.

一. 管道

管道是一种古老且经典, 基于文件操作的通信方案;

管道根据它的特性命名, 是一个可以连接不同进程的数据流, 且数据流是半双工的(单向通信);
其本质就是操作系统在物理内存中创建的一份文件, 不同的进程通过写入或读取文件内容达到交互的目的;

管道又分为 匿名管道命名管道.

1. 匿名管道

匿名管道是一种只能用于具有亲缘关系的进程之间通信的管道, 常用于父子进程.

1.1. 匿名管道的创建

命令行创建

匿名管道可以使用命令创建和使用, 通常使用符号 “|” 来表示管道.

  • 例:
    cat log.txt 的内容被 wc -l (统计数据的行数)指令读取, 打印出 log.txt 文件内容的行数.
    在这里插入图片描述
    原理:
    在这里插入图片描述
pipe() 函数创建

pipe() 函数可以创建一个匿名管道

#include <unistd.h>int pipe(int fd[2]);
  • 参数 fd:输出型参数, 文件描述符数组; 其中 fd[0] 表示读端, fd[1] 表示写端 .
  • 返回值: 若成功, 返回 0 ; 若失败, 返回-1, 并设置错误代码.

例:

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;int main()
{int fd[2];int n = pipe(fd);   // 创建匿名管道if (n == -1)        // 若失败{perror("pipe: ");return 0;}int pid = fork();   // 创建子进程if (pid == -1)      // 若失败{perror("fork: ");return 0;}// 子进程if (pid == 0){close(fd[0]);   // 关闭读端char buffer[] = "i am son";for (int i=0; i<10; i++){// 向管道写入ssize_t sz = write(fd[1], buffer, sizeof(buffer) - 1);if (sz == -1)	// 写入失败{perror("write: ");  break;}sleep(1);}close(fd[1]);   // 关闭写端return 0;}// 父进程close(fd[1]);       // 关闭写端// 从管道读取char buffer[64];while (1){ssize_t sz = read(fd[0], buffer, sizeof(buffer));if (sz == -1)   // 读取失败{perror("read: ");break;}buffer[sz] = 0;if (sz)         // 读取成功cout << buffer << endl;else            // 写端关闭break;}close(fd[0]);       // 关闭读端wait(nullptr);      // 等待子进程return 0;
}

在这里插入图片描述

原理:
父进程使用 pipe() 函数创建并记录匿名管道文件的读写端, 子进程会通过 fork() 继承匿名管道信息, 之后父子进程分别关闭不需要的读或写端, 即可实现进程间的单向通信.
在这里插入图片描述
注: 匿名管道文件是一个由操作系统提供的内存文件, 不需要将数据刷新至磁盘中;

1.2 匿名管道的读写规则

  • 当管道为空时:
    O_NONBLOCK disable: read() 函数调用阻塞, 即进程暂停执行, 直至有数据来到为止;
    O_NONBLOCK enable: read() 函数调用返回 -1, errno 设置为 EAGAIN.
  • 当管道为满时:
    O_NONBLOCK disable: write() 函数调用阻塞, 直至有进程读走数据;
    O_NONBLOCK enable: write() 函数调用返回 -1, errno 设置为 EAGAIN.
  • 若管道的所有写端对应的文件描述符被关闭, 则 read() 函数返回 0;
    若管道的所有读端对应的文件描述符被关闭, 则 write() 函数会产生信号 SIGPIPE, 进而可能导致写端进程退出.
  • 当写入的数据量不大于 PIPE_BUF (管道的大小, defined in <limits.h>)时, Linux 将保证写入的原子性;
    当写入的数据量大于 PIPE_BUF 时, Linux 将不再保证写入的原子性.

也就是管道读写时会出现四种情况:

  • 当管道内容为空, 读端 读取时, 读端进程会被阻塞挂起, 直至管道被写入数据后才会被唤醒;

  • 当管道内容满后, 写端 写入时, 写端进程会被阻塞挂起, 直至管道数据被读取后才会被唤醒;

  • 当写端进程写完数据关闭写端, 读端进程将管道中的数据全部读取后, 再次读取并不会阻塞挂起, 而是直接返回 0 值, 表示管道为空, 并且不会再有数据写入, 应该结束读取了.

  • 当读端进程关闭读端后, 若写端进程再次写入数据, 操作系统会认为是无意义行为, 将其进程强制终止, 写端属于异常退出.

1.3 匿名管道的特点

  • 管道单向通信, 是半双工的一种特殊情况; 数据只能向一个方向流动, 若需要双方通信时, 则需要建立两个管道.
  • 只能使用于具有亲缘关系的进程之间进行通信, 管道信息需要继承获得.
  • 管道是面向字节流的, 数据的读取或写入数量由上层控制.
  • 管道的生命周期跟随进程的, 当进程终止时, 管道资源会被操作系统回收.
  • 管道自带同步与互斥机制, 可以在一定程度上协调进程的读写顺序;

2. 命名管道

命名管道不同于匿名管道, 命名管道实现任意进程的通信.

命名管道其本质和匿名管道相同, 依旧是内存文件, 只不过分配了 inode, 将其映射在磁盘上, 使进程可以通过路径和文件名找到;
不过命名管道并没有被分配 Data block, 所以数据依旧不需要刷新至磁盘中;

命名管道在磁盘上就是一个特殊文件, 类型为 p, 在 Linux 中文件名后有一个 “|” 标志, 并且文件大小永远为 0.
在这里插入图片描述

2.1 命名管道的创建

命令行创建
mkfifo file_name
  • 例:
    在这里插入图片描述
mkfifo() 函数创建
#include <sys/types.h>
#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);
  • 参数:
    pathname: 表示命名管道文件的路径和文件名; 若 pathname 仅含文件名, 则默认将命名管道文件创建在当前路径中.
    mode: 表示命名管道文件的默认权限.

  • 返回值: 若文件创建成功, 返回 0; 若失败, 返回 -1, 并设置 erron;

例:
模拟服务器和客户端的数据交互

  • comm.hpp
#pragma once
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>#define FILE_NAME "fifo"
using namespace std;
  • pipe_server.cc
#include "comm.hpp"int main()
{umask(0);int n = mkfifo(FILE_NAME , 0666);       // 创建命名管道文件if (n == -1){cout << "mkfifo:" << strerror(errno) << endl;return 0;}int fd = open(FILE_NAME, O_RDONLY);     // 打开管道文件if (fd == -1){cout << "open:" << strerror(errno) << endl;return 0;}// 从管道中读取数据char buffer[128];while (1){int n = read(fd, buffer, sizeof(buffer)-1); if (!n)             // 若写端关闭{cout << "server quit!" << endl;break;}else if (n == -1)   // 若读取失败{cout << "read:" << strerror(errno) << endl;return 0;}// 正常读取buffer[n] = 0;      cout << "message: " << buffer << endl;}unlink(FILE_NAME);	//删除管道文件return 0;
}
  • pipe_client.cc
#include "comm.hpp"int main()
{int fd = open(FILE_NAME, O_WRONLY);     // 打开管道文件if (fd == -1){cout << "open:" << strerror(errno) << endl;return 0;}// 写入数据string buffer;while (1){cout << "send: ";cin >> buffer;if (buffer == "quit")   {cout << "client quit!" << endl;break;}int n = write(fd, buffer.c_str(), buffer.size());if (n == -1){cout << "write:" << strerror(errno) << endl;return 0;}}return 0;
}

在这里插入图片描述

2.2 命名管道的读写规则和特点

命名管道的读写规则和特点与匿名管道相同;

但会多两种情况:

  • 当管道文件存在时
    若写端未 open() 打开管道, 读端 open() 管道时, 读端会在 open() 位置堵塞等待写端打开; 相反同理.
    在这里插入图片描述

FIFO(命名管道)与 pipe (匿名管道) 之间唯一的区别在于它们创建与打开的方式不同, 一旦这些工作完成之后, 它们具有相同的语义.

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

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

相关文章

Mongodb入门--头歌实验MongoDB 复制集 分片

一、MongoDB之副本集配置 1.1MongoDB主从复制 主从复制是MongoDB最早使用的复制方式&#xff0c; 该复制方式易于配置&#xff0c;并且可以支持任意数量的从节点服务器&#xff0c;与使用单节点模式相比有如下优点&#xff1a; 在从服务器上存储数据副本&#xff0c;提高了数…

【软件工程】UML用例图介绍和实例说明

文章目录 1、什么是用例图2、用例图的作用3、怎么画用例图4、三要素说明5、实例说明 1、什么是用例图 用例图&#xff08;Use Case Diagram&#xff09;是统一建模语言&#xff08;UML&#xff09;的一种图&#xff0c;它主要用于描述系统的功能和用户&#xff08;参与者&…

【C++学习】C++智能指针:提高代码安全与性能的利器

文章标题 智能指针的提出智能指针概念及使用RAII 智能指针的原理C库多种智能指针详解版本一&#xff1a;std::auto_ptr&#xff08;C98&#xff09;1. std::auto_ptr 使用2. std::auto_ptr 原理3. std::auto_ptr 模拟实现 版本二&#xff1a;unique_ptr (C11)1. unique_ptr 的使…

数码相框-显示JPG图片

LCD控制器会将LCD上的屏幕数据映射在相应的显存位置上。 通过libjpeg把jpg图片解压出来RGB原始数据。 libjpeg是使用c语言实现的读写jpeg文件的库。 使用libjpeg的应用程序是以"scanline"为单位进行图像处理的。 libjpeg解压图片的步骤&#xff1a; libjpeg的使…

2023年MathorCup数学建模D题航空安全风险分析和飞行技术评估问题解题全过程文档加程序

2023年第十三届MathorCup高校数学建模挑战赛 D题 航空安全风险分析和飞行技术评估问题 原题再现 飞行安全是民航运输业赖以生存和发展的基础。随着我国民航业的快速发展&#xff0c;针对飞行安全问题的研究显得越来越重要。2022 年 3 月 21 日&#xff0c;“3.21”空难的发生…

STM32之HAL开发——FatFs文件系统移植

FatFs文件系统移植 FatFs 程序结构图 移植 FatFs 之前我们先通过 FatFs 的程序结构图了解 FatFs 在程序中的关系网络 用户应用程序需要由用户编写&#xff0c;想实现什么功能就编写什么的程序&#xff0c;一般我们只用到 f_mount()、f_open()、 f_write()、f_read() 就可以…

【vue】watchEffect 自动侦听器

watchEffect&#xff1a;自动监听值的变化 获取旧值时&#xff0c;不是很方便&#xff0c;建议用watch <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevic…

Android Studio 使用Flutter开发第一个Web页面(进行中)

附上Flutter官方文档 1、新建Flutter项目&#xff08;需要勾选web选项&#xff09; 新建项目构成为&#xff1a; 2、配置 Flutter 使用 path 策略 官方文档 在main.dart中&#xff0c;需要导入flutter_web_plugins/url_strategy.dart包&#xff0c;并在main(){}函数中usePath…

影响小程序SSL证书收费标准的因素有哪些?

在当今互联网时代&#xff0c;移动应用发展日新月异&#xff0c;小程序逐渐成为广大企业和个人开发者的心仪之选。然而&#xff0c;伴随小程序的广泛应用&#xff0c;安全问题和用户信任显得尤为关键。为了确保小程序的信息传输安全&#xff0c;SSL证书成为了一项基础配置。那么…

MySQL 表管理

目录 建库 语法&#xff1a; 库名命名规则&#xff1a; 相关命令&#xff1a; 建表 语法&#xff1a; 相关命令&#xff1a; 修改表 语法&#xff1a; 常用操作命令 复制表 数据类型 MySQL的10种常用数据类型&#xff1a; 数据的导入和导出 导入&#xff1a; 格…

Acrobat Pro DC 2023 for mac直装激活版 pdf编辑处理工具

Acrobat Pro DC 2023 for Mac是一款功能强大的PDF编辑器&#xff0c;为用户提供了全面且高效的PDF处理体验。 软件下载&#xff1a;Acrobat Pro DC 2023 for mac直装激活版下载 首先&#xff0c;它支持用户从现有文档创建PDF&#xff0c;或者将其他文件格式如图片、网页等轻松转…

SpringBoot之集成Redis

SpringBoot之集成Redis 一、Redis集成简介二、集成步骤2.1 添加依赖2.2 添加配置2.3 项目中使用 三、工具类封装四、序列化 &#xff08;正常都需要自定义序列化&#xff09;五、分布式锁&#xff08;一&#xff09;RedisTemplate 去实现场景一&#xff1a;单体应用场景二&…

自动化测试(selenium篇)

这次我们来介绍selenium 我们主要来讲解这几个要点 1.什么是自动化测试 2.什么是selenium 3.为什么来讲selenium 4.selenium的环境搭建 5.selenium的 API 1.什么是自动化测试 自动化测试指软件测试的自动化&#xff0c;在预设状态下运行应用程序或者系统&#xff0c;预设条…

海外媒体发稿:探究7个旅游业媒体套餐背后的秘密-华媒舍

旅游业媒体套餐对于旅游行业来说扮演着重要的角色&#xff0c;帮助企业在竞争激烈的市场中宣传推广&#xff0c;吸引更多的游客。在这篇文章中&#xff0c;我们将深入探究7个旅游业媒体套餐背后的秘密&#xff0c;为您揭示其真正的价值和影响。 1. 平台选择的关键 在选择旅游业…

【40分钟速成智能风控11】数据测试与应用

目录 ​编辑 数据测试与应用 联合建模机制 数据质量评估 覆盖率 稳定性 模型效果 投资回报率 线上应用 数据安全合规 数据测试与应用 智能风控模型的搭建离不开机构内外部的数据源&#xff0c;如何从海量数据源中挑选出最合适的部分进行特征工程和风控建模&#xff…

高创新 | [24年新算法]NRBO-XGBoost回归+交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测

高创新 | [24年新算法]NRBO-XGBoost回归交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测 目录 高创新 | [24年新算法]NRBO-XGBoost回归交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现 [24年新算…

Centos7 搭建Mongodb 分片集群4.0/ PSA(三成员副本集)

MongoDB 简介:1、优点和缺点:2、MongoDB适用的业务场景:Centos7 搭建Mongodb 分片集群一、安装MongoDB社区版4.01、配置程序包管理系统(`yum`)2、安装对应版本的MongoDB软件包。3、创建运行mongodb的目录并禁用SELinux4、修改文件打开数5、初始化系统5.1、创建config配置…

性能测试-数据库优化二(SQL的优化、数据库拆表、分表分区,读写分离、redis)

数据库优化 explain select 重点&#xff1a; type类型&#xff0c;rows行数&#xff0c;extra SQL的优化 在写on语句时&#xff0c;将数据量小的表放左边&#xff0c;大表写右边where后面的条件尽可能用索引字段&#xff0c;复合索引时&#xff0c;最好按复合索引顺序写wh…

请求分发场景下的鉴权问题

说明&#xff1a;记录一次对请求分发&#xff0c;无法登录系统的问题。 场景 如下&#xff0c;在此结构下&#xff0c;如何判断该用户是已登录的用户&#xff1b; 常规操作&#xff0c;用户登录后给用户发Token&#xff0c;同时将发放的Token存入到Redis中。要求用户后续请求…

【Jenkins】Jenkins自动化工具介绍

目录 技术背景常规的手动打包步骤 Jenkins简介起源与发展Jenkins的核心价值1.自动化1.1代码构建1.2测试自动化1.3自动部署 2.持续集成与持续部署CI/CD的概念如何减少集成问题更快速地发布软件版本 Jenkins优势Jenkins的主要竞争对手Travis CI:CircleCI:GitLab CI: Jenkins与其他…