『 Linux 』命名管道

news2024/11/24 14:46:13

文章目录

    • 命名管道与匿名管道
    • 命名管道特点
    • 命名管道的理解
    • 命名管道实现两个毫无关联的进程间通信


命名管道与匿名管道

请添加图片描述

命名管道是管道的一种,数据流向为单向故被称为管道;

与匿名管道相同属于一种内存级文件;

区别如下:

  • 名字

    • 匿名管道

      没有名字,只存在于内存当中(类似内核缓冲区);

    • 命名管道

      有名字,基于文件系统,有对应的Inode以及对应属性;

      虽然存在Inode以及对应属性,但其对应的磁盘中的数据块指向为空,这表示命名管道不占用实际磁盘空间;

      其没有刷盘动作,因此对应数据不会刷新至磁盘中;

  • 通信进程

    • 匿名管道

      只适用于具有亲缘关系的进程进行通信;

    • 命名管道

      可适用于毫不相关的进程间的通信;

  • 数据流向

    • 匿名管道

      数据流向为单向;

    • 命名管道

      数据流向可以是单向也可以是双向(默认情况下的数据流向为单向);

  • 创建方式

    • 匿名管道

      在进程中调用pipe()系统调用接口创建管道文件;

      创建管道文件后调用fork()系统调用接口创建子进程从而为父子(有亲缘关系的)进程创建通信信道;

    • 命名管道

      在命令行中通常使用mkfifo命令创建管道;

      $ mkfifo myfifo;ll -i
      total 4
      2360390 prw-rw-r-- 1 _LJP _LJP    0 Jul 15 13:41 myfifo
      
      # 在bash中使用fifo命令创建一个名为myfifo的命名管道文件,并用 ll -i 选项查看命名管道的状态以及对应的Inode号
      

      结果来看命名管道存在对应的Inode;

      也可通过在进程中直接调用mkfifo()系统调用接口创建命名管道文件;

      NAME
             mkfifo  -  make  a  FIFO  special file (a named
             pipe)
      
      SYNOPSIS
             #include <sys/types.h>
             #include <sys/stat.h>
      
             int mkfifo(const char *pathname, mode_t mode);
      
      RETURN VALUE
             On  success mkfifo() returns 0.  In the case of
             an error, -1 is returned (in which case,  errno
             is set appropriately).
      
      

      调用mkfifo()系统调用接口时需要包含<sys/types.h>,<sys/stat.h>的头文件;

      传入参数pathnamemode分别代表 路径+管道文件名权限(匿名管道也是一个文件,需要具有权限) ;

      #include <sys/stat.h>
      #include <sys/types.h>
      
      #include <iostream>
      using namespace std;
      
      int main() {
        //
        mkfifo("./myfifo", 0664);
        return 0;
      }
      

      结果:

      $ ll -i;make;./mytest;make clean;ll -i
      total 8
      2361492 -rw-rw-r-- 1 _LJP _LJP  80 Jul 15 14:03 makefile
      2361488 -rw-rw-r-- 1 _LJP _LJP 147 Jul 15 14:02 test.cc
      g++ -o mytest test.cc -std=c++11 -g -Wall
      rm mytest
      total 8
      2361492 -rw-rw-r-- 1 _LJP _LJP  80 Jul 15 14:03 makefile
      2361494 prw-rw-r-- 1 _LJP _LJP   0 Jul 15 14:06 myfifo #命名管道文件被创建
      2361488 -rw-rw-r-- 1 _LJP _LJP 147 Jul 15 14:02 test.cc
      

      其中命名管道文件权限的最开头的p表示这个文件类型为一个管道文件(pipe);


命名管道特点

请添加图片描述

命名管道读写端在进行通信时将会互相等待;

  • 读端

    当管道内不存在数据时读端会进行阻塞并等待写端向管道内写入数据;

    # 读端
    $ cat myfifo 
    				# 进行阻塞等待写端写入
    #-------------------
    # 此时写端向管道内写入
    $ echo "hello world" > myfifo
    #-------------------
    # 读端
    $ cat myfifo 
    hello world 	# 停止阻塞将管道文件内数据进行读取
    
  • 写端

    当管道内的数据没有被读端读取时写端会进行阻塞等待读端将当前管道内的数据进行读取;

    # 写端
    $ echo "hello world" > myfifo
    					# 进行堵塞等待读端读取
    #-------------------
    # 此时打开读端读取命名管道文件内信息
    $ cat myfifo 
    hello world
    #-------------------
    $ echo "hello world" > myfifo
    $ 					# 写端停止阻塞
    

命名管道虽然具有Inode以及对应的属性,但其并不占用实际磁盘空间,只是用于数据传输,所以命名管道文件的大小始终为0;

  • 示例

    # [会话1]
    $ while :; do echo "hello myfifo" > myfifo ;sleep 1 ;done
    # ------------------------
    # [会话2]
    $ while :; do cat
     myfifo ;done
    hello myfifo
    hello myfifo
    hello myfifo
    hello myfifo
    ...
    # ------------------------
    # [会话3]
    $ ll
    total 8
    prw-rw-r-- 1 _LJP _LJP   0 Jul 15 14:39 myfifo
    $ ll
    total 8
    prw-rw-r-- 1 _LJP _LJP   0 Jul 15 14:39 myfifo
    

命名管道的理解

请添加图片描述

当两个不同的进程同时打开同一个文件时在内核当中也只是打开了一个文件;

文件系统与进程之间是同级关系且进行了解耦合;

  • 进程间通信的前提

    先让不同的进程看到同一份资源;

进程打开文件时文件系统不需要因为被打开而对文件进行拷贝复制等操作;

命名管道不占用实际磁盘空间,只是用于传输,不存在刷盘(写入磁盘)的动作,故实际上使用的也是该文件的内核缓冲区;

两个进程通过管道文件的 路径+文件名 再通过Inode编号来确定两个进程打开的是同一个管道文件( 路径+文件名 具有唯一性);


命名管道实现两个毫无关联的进程间通信

请添加图片描述

  • 准备

    • server.cc文件

      模拟实现服务端,用于管理命名管道文件,接收管道内文件并进行打印;

    • client.cc文件

      模拟实现客户端,用于向客户端写入数据;

    • comm.hpp文件

      用于包含所需头文件及简单声明定义所需常量等;

  • 具体思路

    两个毫不相关的进程,其中一个进程用来创建管道文件并维护管道文件,同时负责接收另一个进程向管道文件内写入的数据;

    另一个进程用来向管道文件内写入数据从而进行简单交互;

  • comm.hpp

    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    #include <cstdlib>
    #include <iostream>
    #include <string>
    
    #define PIPEFILE "./myfifo" // 管道文件文件名
    #define MODE 0666			// 管道文件权限
    
    #define SIZE 1024			// 缓冲区所需大小
    
    using namespace std;
    
    enum { FIFO_CREATE_ERR = 1, FIFO_DELETE_ERR, FIFO_OPEN_ERR }; // 枚举对应错误码
    
    class PipeInit {
     public:
      // 创建管道文件
      PipeInit() {
        int n = mkfifo(PIPEFILE, MODE);
        if (n == -1) {
          cerr << "CREATE PIPE FAIL" << endl;
          exit(FIFO_CREATE_ERR);
        }
      }
      // 销毁管道文件
      ~PipeInit() {
        int m = unlink(PIPEFILE);
        if (m == -1) {
          cerr << "DEL PIPE FAIL" << endl;
          exit(FIFO_DELETE_ERR);
        }
      }
    };
    

    创建一个管道类用于管理管道文件,即利用其构造函数创建管道文件,在退出后析构函数释放对应管道文件;

    enum枚举出错误信息常量;

  • server.cc

    
    #include "comm.hpp"
    
    // 服务端管理管道文件
    
    int main() {
      // 创建管道信道
      PipeInit myfifo;
    
      // 打开管道文件
      int fd = open(PIPEFILE, O_RDONLY);
      if (fd < 0) {
        cerr << "SERVER OPEN PIPE FAIL" << endl;
        exit(FIFO_OPEN_ERR);
      }
      cout << "Server open file done" << endl;
      // 开始进行通信
      char buffer[SIZE] = {0};  // 清空 当做字符串读取
      while (true) {
        int x = read(fd, buffer, sizeof(buffer));
        if (x > 0) {
          buffer[x] = '\0';
          cout << "server get a massage from client# ";
          cout << buffer << endl;
        }
        if (x == 0) {
          cout << "Client quit" << endl;
          break;
        }
      }
    
      // 结束通信关闭管道
      close(fd);
      return 0;
    }
    

    实例化一个对象依次构建对话对应所需信道;

    调用open()系统调用接口打开管道文件;

    创建buffer[]字符串充当缓冲区,并调用read()系统调用接口从命名管道文件中读取数据并进行打印;

    当写端被关闭时读端所调用的read()系统调用接口将返回0表示读到了文件末尾,作判断并结束程序;

    对话完毕后调用系统调用接口close()关闭对应文件描述符;

  • client.cc

    
    
    #include "comm.hpp"
    
    int main() {
      //
      int fd = open(PIPEFILE, O_WRONLY);
      if (fd < 0) {
        cerr << "CLIENT OPEN PIPE FAIL" << endl;
        exit(FIFO_OPEN_ERR);
      }
      cout << "Client open file done" << endl;
      string line;
      while (true) {
        cout << "Please Enter Your Massage@ ";
        getline(cin, line);
        write(fd, line.c_str(), line.size());
      }
      close(fd);
      return 0;
    }
    

    调用系统调用接口open()打开命名管道文件;

    创建缓冲区buffer[]并调用getline(cin,buffer)从键盘获取数据并存储至缓冲区中;

    调用write()系统调用接口将缓冲区中数据写入至命名管道文件中;

    对话完成后调用系统调用接口close()关闭对应文件描述符;

  • 完整代码(供参考):

    [参考代码(gitee) - DIo夹心小面包 (半介莽夫)]

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

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

相关文章

【Visual Studio】Visual Studio使用技巧及报错解决合集

目录 目录 一.概述 二.Visual Studio报错问题及解决方法 三.Visual Studio操作过程中遇到的问题及解决方法 四.Visual Studio编译优化选项 五.Visual Studio快捷键 一.概述 持续更新Visual Studio报错及解决方法&#xff0c;包括Visual Studio报错问题及解决方法、Visua…

mac电脑pdf合并,macpdf合并成一个pdf

在数字化办公和学习的今天&#xff0c;pdf文件因其跨平台兼容性强、格式稳定而成为了最受欢迎的文档格式之一。但随之而来的问题也接踵而至&#xff0c;如何将多个pdf文件合并为一个&#xff1f;这不仅关系到文档的整洁性&#xff0c;更是时间管理的重要环节。今天&#xff0c;…

STM32+TMC2209控制步进电机正反转。

STM32F103ZET6TMC2209控制步进电机正反转 1. 步进电机介绍2 驱动器TMC2209介绍2.1 引脚图及其功能2.2 细分介绍2.3 TMC控制驱动器接法 3 控制器介绍3.1 确定控制引脚3.2 UBEMX配置3.2.1 GPIO配置3.2.2 NVIC配置3.2.3 RCC配置3.2.4 SYS配置3.2.5 USRAT2配置&#xff08;PS:没用上…

【JS红宝书学习笔记】第25章 客户端存储

第25章 客户端存储 Cookie HTTP是无状态的&#xff0c;也就是说&#xff0c;你这次访问服务器&#xff0c;关闭后再次访问服务器&#xff0c;服务器是意识不到又是你来访问的。 登录时&#xff0c;浏览器需要帮我们在每一次请求里加入用户名和密码&#xff0c;这样才能做到保…

(WRF-UCM)高精度城市化气象动力模拟

气候变化及应对是政府、科学界及商业界关注的焦点。气候是多个领域&#xff08;生态、水资源、风资源及碳中和等问题&#xff09;的主要驱动因素&#xff0c;合理认知气候变化有利于解释生态环境变化机理及过程&#xff0c;而了解现在、未来气候变化则是进行生态、环境及能源评…

Win11鼠标卡顿 - 解决方案

问题 使用Win11系统使&#xff0c;鼠标点击任务栏的控制中心&#xff08;如下图&#xff09;时&#xff0c;鼠标会有3秒左右的卡顿&#xff0c;同时整个显示屏幕也有一定程度的卡顿。 问题原因 排除鼠标问题&#xff1a;更换过不同类型的鼠标&#xff0c;以及不同的连接方式…

【计算机毕业设计】学生心理咨询评估系统设计与实现【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

[BJDCTF2020]EzPHP1

知识点&#xff1a;1. url编码绕过 2. %0a绕过 3. post优先级绕过 4. php伪协议 5. 数组的强类型比较绕过 6. 取反绕过 进入之后发现了一个很帅气的页面&#x1f60e;~ 看看网页源代码试试~ 是base32编码&#xff0c;尝试一下解码. https://www.qqxiuzi.cn/bianma/base.php 解…

qt 创建一个左侧边线拖拽的矩形

1.概要 2.代码 2.1 代码第一版 在Qt中&#xff0c;要创建一个可以向左侧拖拽边线的矩形&#xff0c;你需要自定义一个QGraphicsRectItem的子类&#xff0c;并重写其事件处理函数来响应鼠标的拖拽动作。以下是一个简单的实现示例&#xff1a; #include <QApplication>…

DHCP服务、FTP服务

一、DHCP 1.1 DHCP是什么 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;是一种网络协议&#xff0c;用于自动分配 IP 地址和其他网络配置信息给网络中的设备 1.2 DHCP的好处 自动化: 减少了手动配置 IP 地址和网络参数的工…

C++客户端Qt开发——常用控件(多元素控件)

5.多元素控件 Qt中提供的多元素控件有&#xff1a; QListWidget QListView QTablewidget QTableview QTreewidget QTreeview xxWidget和xView之间的区别 以QTableWidget和QTableView为例. QTableView是基于MVC设计的控件.QTableView自身不持有数据.使用QTableView的时候需要…

【密码学】密码学数学基础:剩余系

不得不啃的密码学数学基础之剩余系是个啥&#xff1f;数学里面有好多的定义都有前置的数学概念&#xff0c;要想弄懂剩余系还得先说说“同余”。 一、同余 那么“同余”有是个什么呢&#xff1f;在谈论“同余”之前&#xff0c;我们先圈定个讨论的范围。接下来讨论的都是整数集…

PyTorch Autograd内部实现

优化&#xff1a;如果is_leafFalse&#xff0c;则说明不需要该Tensor的grad&#xff0c;所以&#xff0c;grad_fn直接将output梯度传递给下一个grad_fn了&#xff0c;绕开对该Tensor的grad的更新&#xff1b;

C语言 | Leetcode C语言题解之第235题二叉搜索树的最近公共祖先

题目&#xff1a; 题解&#xff1a; struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {struct TreeNode* ancestor root;while (true) {if (p->val < ancestor->val && q->val < ancestor-&g…

信息系统项目管理师(高项)—学习笔记二

第一章 以下是上一篇&#xff08;信息系统项目管理师&#xff08;高项&#xff09;—学习笔记&#xff09;的续写&#xff0c;因为是之前记录的&#xff0c;这一篇还是细致到每一个小节的内容&#xff0c;有些过于复杂了&#xff0c;后续会简化~ 1.3 现代化创新发展 党的十九…

干货丨ChatGPT高阶玩法(上)

正文共1321字 预计阅读时间4分钟 是的,你没有看错,上面这段这么像人写的内容其实是由ChatGPT这个机器人AI生成的(我只稍加修改了几个字),发送下面第一个提示词口令,然后加以进一步引导并不断改进就可以得到你想要的结果,具体操作见文中图片。 使用说明 以下【】里的内…

Unable to obtain driver using Selenium Manager: Selenium Manager failed解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

《Windows API 每日一练》10.1 模态对话框

对话框分“模态”和“非模态”两种&#xff0c;其中模态对话框最为常见。当程序显示一个模态对话框时&#xff0c;用户不能在对话框和该程序的其他窗口之间进行切换。用户必须先明确地终止该对话框。这通常由单击OK或Cancel按钮来实现。但是当对话框正在显示时&#xff0c;用户…

[Linux]基本指令(二)

一些剩下的指令部分 mv指令&#xff08;重要&#xff09; mv 命令是 move 的缩写&#xff0c;可以用来移动文件或者将文件改名&#xff08; move (rename) files &#xff09;&#xff0c;是 Linux 系统下常用的命令&#xff0c; 经常用来备份文件或者目录。 语法 : mv [ 选项…

京东.Vision首登苹果Vision Pro 背后的技术探索

去年6月&#xff0c;苹果正式发布首款头显设备Apple Vision Pro&#xff0c;今年6月28号&#xff0c;Apple Vision Pro正式在中国发售。京东.Vision作为首批原生应用登陆Vision Pro平台&#xff0c;首期以家电家居与潮流数码产品作为切入口&#xff0c;未来将逐步拓展至全品类&…