『 Linux 』命名管道

文章目录

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


命名管道与匿名管道

请添加图片描述

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

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

区别如下:

  • 名字

    • 匿名管道

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

    • 命名管道

      有名字,基于文件系统,有对应的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()系统调用接口创建命名管道文件;

      NAMEmkfifo  -  make  a  FIFO  special file (a namedpipe)SYNOPSIS#include <sys/types.h>#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);RETURN VALUEOn  success mkfifo() returns 0.  In the case ofan error, -1 is returned (in which case,  errnois 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 catmyfifo ;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.mzph.cn/news/872276.shtml

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

相关文章

【软件测试】编写测试用例篇

前面部分主要是编写测试用例的方法和方向&#xff0c;后面一部分是编写出具体的测试用例 目录 什么是测试用例 1.设计测试用例的万能公式 1.1.从思维出发 1.2.万能公式 1.3.弱网测试 1.4.安装与卸载测试 2.设计测试用例的方法 2.1.基于需求的设计方法 2.2.等价类 2.3…

测试开发面经总结(三)

TCP三次握手 TCP 是面向连接的协议&#xff0c;所以使用 TCP 前必须先建立连接&#xff0c;而建立连接是通过三次握手来进行的。 一开始&#xff0c;客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口&#xff0c;处于 LISTEN 状态 客户端会随机初始化序号&…

原来,BI数据分析也是有模板的

在当今数据驱动的时代&#xff0c;商业智能&#xff08;BI&#xff09;数据分析已经成为企业决策的重要工具。然而&#xff0c;很多人可能并不了解&#xff0c;BI数据分析并非从零开始&#xff0c;而是可以依托现成的模板和解决方案来快速搭建和实施的。以奥威BI方案为例&#…

kotlin get set

在 Kotlin 中&#xff0c;如果想实现一个类的属性可以从外部读取但不能修改&#xff0c;可以使用自定义的 getter 和 private setter。以下是一个示例代码&#xff1a; class MyClass {var myProperty: Stringprivate set // 使 setter 私有化&#xff0c;外部无法修改get // …

React+TS前台项目实战(二十九)-- 首页构建之性能优化实现首页Echarts模块数据渲染

文章目录 前言Echart模块源码功能分析数据渲染一、HashRateEchart统计图1. 功能分析2. 代码详细注释 二、BlockTimeChart统计图1. 功能分析2. 代码详细注释 三、使用方式四. 数据渲染后效果如下 总结 前言 还记得之前我们创建的 高性能可配置Echarts组件 吗&#xff1f;今天我…

redis 配置文件参数详解

1、redis.conf 通用类 Redis的配置文件是一个文本文件&#xff0c;通常名为redis.conf。以下是一些常见配置项的解释和示例&#xff1a; 1、bind 127.0.0.1&#xff1a;绑定的主机地址 2、 protected-mode ,默认是开启状态&#xff0c;一般不需要修改&#xff0c;可以保证服务…

k8s nacos2.0.3 连接 mysql8.0 提示No Datasource set问题

主要因为是连接数据库字符串未指定时区问题 将 mysql-service-db-param 参数追加 serverTimezoneUTC 即可连接成功。 k8s集群yaml文件 apiVersion: v1 data:mysql_root_password: MTIzNDU2 kind: Secret metadata:name: mysql-passwordnamespace: test---apiVersion: v1 dat…

唯众物联网综合实训台 物联网实验室建设方案

物联网综合实训装置 物联网工程应用综合实训台是我公司针对职业院校物联网行业综合技能型人才培养&#xff0c;综合运用传感器技术、RFID技术、接口控制技术、无线传感网技术、Android应用开发等&#xff0c;配合实训台上的433M无线通信设备、ZigBee节点、射频设备、控制设备、…

智能家居产品公司网站源码,自适应布局设计,带完整演示数据

适合各类智能家居电子产品使用的网站源码&#xff0c;深色大气设计&#xff0c;自适应布局设计&#xff0c;pc手机均可完美适配&#xff0c;带完整演示数据。 独家原创资源。源码是asp开发的&#xff0c;数据库是access&#xff0c;主流的虚拟主机空间都支持asp&#xff0c;直…

第三届经济、智慧金融与当代贸易国际学术会议(ESFCT2024)

【五大高校联合支持】第三届经济、智慧金融与当代贸易国际学术会议(ESFCT 2024) 2024 3rd International Conference on Economics, Smart Finance and Contemporary Trade 文章投稿均可免费参会 高录用快见刊【最快会后1-2个月左右见刊】【最快刊后1个月内上知网&谷歌学…

漏洞-Alibaba Nacos derby 远程代码执行漏洞

【漏洞详情】 漏洞描述&#xff1a;Alibaba Nacos derby 存在远程代码执行漏洞&#xff0c;由于Alibaba Nacos部分版本中derby数据库默认可以未授权访问&#xff0c;恶意攻击者利用此漏洞可以未授权执行SQL语句&#xff0c;从而远程加载恶意构造的jar包&#xff0c;最终导致任意…

【人工智能】高级搜索技术(模拟退火搜索算法和遗传算法解决旅行商问题)

目录 一、旅行商问题 1. 需求分析 2. 数据结构、功能模块设计与说明 2.1 数据结构 &#xff08;1&#xff09;模拟退火搜索算法 &#xff08;2&#xff09;遗传算法 2.2 功能模块设计 &#xff08;1&#xff09;模拟退火搜索算法 &#xff08;2&#xff09;遗传算法 …

在 PostgreSQL 里如何处理数据的存储优化和查询复杂度的平衡?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 在 PostgreSQL 里如何处理数据的存储优化和查询复杂度的平衡&#xff1f;一、理解数据存储优化和查询复…

前缀匹配工具之IP-Prefix

基本概念: IP-Prefix&#xff0c;即IP前缀&#xff0c;相比传统ACL&#xff0c;它能够基于路由前缀与路由掩码进行匹配 例如&#xff0c;192.168.0.0/16&#xff0c;192.168.0.0/24&#xff0c;这两条前缀相同&#xff0c;但是掩码不同的路由流量 若是ACL规则如是写下&#…

亚马逊、ebay、沃尔玛卖家打造爆款如何利用测评提高转化率?

做亚马逊、速卖通、ebay只有打造爆款&#xff0c;才能够挣到钱&#xff0c;如果一年到头&#xff0c;不断测款&#xff0c;不断测试不同的广告打法&#xff0c;那么代表了什么&#xff1f;代表了你的试错成本相当高&#xff0c;一不小心&#xff0c;分分钟就能够把手头上仅有的…

css2024

1 :has() Selector <ul><li><label> <input type"radio" name"source" />谷歌</label></li><li><label> <input type"radio" name"source" />口碑</label></li>&l…

工业智能网关的边缘计算能力赋能工业4.0

边缘计算是将数据处理和分析能力推向网络边缘的技术&#xff0c;使得终端设备能够实时、快速地响应环境变化&#xff0c;并做出相应决策。在智能制造中&#xff0c;通过5G工业网关的边缘计算能力&#xff0c;企业可以实现对生产线上大量传感器数据的实时采集、处理和分析&#…

开发实战经验分享:互联网医院系统源码与在线问诊APP搭建

作为一名软件开发者&#xff0c;笔者有幸参与了多个互联网医院系统的开发项目&#xff0c;并在此过程中积累了丰富的实战经验。本文将结合我的开发经验&#xff0c;分享互联网医院系统源码的设计与在线问诊APP的搭建过程。 一、需求分析 在开发任何系统之前&#xff0c;首先要…

用chatgpt写了个二级导航,我全程一个代码没写,都是复制粘贴

今天心血来潮&#xff0c;让chatgpt给我写个移动端的二级导航菜单&#xff0c;效果如下&#xff1a; 1、两级导航&#xff0c;竖向排列&#xff0c;一级导航默认显示&#xff0c;二级隐藏 2、抽屉伸缩效果&#xff0c;点击一级导航&#xff0c;展开二级导航&#xff0c;再次点…

视觉SLAM十四讲

一、前言 课件源码:gaoxiang12/slambook (github.com) 操作系统:ubuntu18.04 系统架构:arrch64或amd架构 二、KDevelop 的安装 安装 1. 安装gcc(编译器) amd :sudo apt-get build-dep gcc sudo apt-get install build-essential arrch64:详见编译conda没有的包…