【Linux】—— 命名管道详解

这篇具有很好参考价值的文章主要介绍了【Linux】—— 命名管道详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

命名管道是一种在操作系统中用于进程间通信的机制,它允许不同的进程之间通过管道进行数据交换。与匿名管道相比,命名管道具有更多的灵活性和功能。在本博客中,我们将深入探讨命名管道的概念、用途以及如何在编程中使用它们。

目录

(一)什么是命名管道

(二)命名管道原理理解

2.1 创建一个命名管道

2.2 命名管道原理

(三)代码示例

3.1命名管道的打开规则

3.2 实现server&client通信 

 (四)小结


(一)什么是命名管道

命名管道是一种具有独特标识符(通常是文件路径)的管道。它允许不同进程通过该标识符进行通信。与无名管道不同,命名管道存在于文件系统中,使得它们能够跨越进程和甚至计算机边界进行通信。

  1. 管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
  2. 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
  3. 命名管道是一种特殊类型的文件
     

(二)命名管道原理理解

2.1 创建一个命名管道

1️⃣命名管道可以从命令行上创建,命令行方法是使用下面这个命令

mkfifo filename
  • 我们不了解的话可以通过man手册去对这个函数进行学习: 

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

 示例演示:

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

【解释说明】 

  • 我们可以先手动的创建一个管道文件,给它起一个 fifo 的文件名,创建好之后我们就看到了当前目录下存在了一个文件叫做 fifo ;
  • 其次我们可以发现它的文件类型前面以P开头,当大家看到P开头的,会能想到什么?在之前我给大家在讲我们Linux基础命令的时候说过一个话题叫做文件类型:以 - 开头普通文件、以D开头为目录文件、以L开头为链接文件L开头的叫做软链接、这里以P开头叫做管道文件,这时候在磁盘上存在了一个管道文件

  接下来,我准备向文件中写入数据:

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

【解释说明】  

  • 在我们的理解中把它写到文件当中,此时就相当于当我一敲回车,echo对应的这个东西就会变成进程;
  • 然后,执行我们向显示器当中打印,经过重定向,它最终不向显示器文件打印,而向管道文件中打印,所以底层作为重定向是没问题的;
  • 紧接着我们就尝试去写了,但当前呢它卡在这里的,什么都没做,我们再看一下当前这个管道文件里,当前显示的是零,好像没有写入啊;
  • 这是因为管道文件有种特殊特性,虽然在磁盘当中创建了这个 fifo,但它仅仅是一种符号,那么对于这种符号呢,将来你向这个文件里写入的消息,并没有或者并不会刷新落实到磁盘上,而是只帮我们在这里直接 echo,然后写入管道文件当中,但是管道文件当前是内存级的,所以你的大小没有变。

接下来,我们在尝试一下输出重定向操作:

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

 【解释说明】  

  • 对于 cat 指令默认就是从显示器当中进行读取,你输什么它给你打印什么;
  • cat fifo 可以直接从管道文件当中输出重对象,将曾经他向管道里写的东西写到它里面;
  • 另外cat也是一条命令,它一旦启动就会变成进程,所以这是一个进程,这俩进程没有任何关系,然后我们这个hello world 的消息最终就打印了出来,这种通讯方式我们就称之为叫做命名管道。

 接下来,我再改一下代码逻辑,再给大家分析一波:

【解释说明】

  • 在进行显示的时候,我让它每隔一秒进行向我们显示器当中打印一条hello world;
  • 但我不想往显示器打印,我想让往管道打印,此时上述那一堆就对应的一个进程,向我们对应的管道文件当中写入;
  • 那么对于 fifo 此时呢,我们就看到本来应该显示到这个显示器文件这个终端的字符串,最终经过管道被重定向到了右端。

2️⃣ 命名管道也可以从程序里创建,相关函数有:

int mkfifo(const char *filename,mode_t mode);

2.2 命名管道原理

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

【解释说明】 

  • 现在假设左边框框里,它是我们对应的操作系统内部的一大堆的数据结构,和它对应的磁盘组成;
  • 如果磁盘里有一个文件,现在有一个问题,如果我有一个进程要打开它,这是个进程,打开一个文件,有自己的文件描述符表,然后012定义的是标准输入标准输出标准错误这;
  • 此时,对应的要打开我们对应的这个文件,怎么打开呢?我曾经讲过一个文件如果不打开,它就在磁盘上静静的躺着,就有了我们之前讲的分区,然后格式化,然后有文件系统等;
  • 紧接着,对应的这个磁盘文件,它里面还可以去包含文件相关的属性inode,还有它对应的缓冲区等等,一旦它被打开了,首先要在操作系统内为该文件创建对应的struct file对象,然后这个struct file对象它有对应的自己的缓冲区;
  • 在结构体当中,有指针指向它的缓冲区,实际上它里面严格上讲应该是指向它inode,然后进一步指向缓冲区

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

【解释说明】  

  •  我们让父进程创建子进程的时候,子进程会继承父进程的文件描述符表;
  • 所以对于子进程,它直接继承父进程的文件描表之后,它会把这个值拷下来,拷下来之后,他俩就指向同一个文件了;

 上诉是第一种情况,假设如果又来了一个进程,他也要有自己的文件描述符表,紧接着有一个小问题?

  • 如果这个进程此时也打开磁盘中的这个文件了,还用不用再在操作系统内部给他创建一个对应的struct file 结构体,然后给他创建一个缓冲区,然后这样去搞呢?

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

【解释说明】 

  •  其实大可不必;
  • 因为在正常的情况下,对应的文件的属性的值呢数字是一样的,所以操作系统内根本就不需要维护对应的两个一样的结构体;

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

【解释说明】  

  •  所以对于我们来讲,实际上当你想打开这个文件时,当新进程想打开其他文件时,新进程先做的第一件事情是在所有已经打开的文件列表里去找这个文件是否已经被打开了,没有被打开则创建,如果已经打开了;
  • 直接把对应的我们struct file对象的地址填入到对应的下标里,而对应的这个struct file对象里面包含一个叫做ref,我们称之为引用计数;
  • 这个引用计数指向的时候,默认是1,再有进程打开它就变成2了,当你关闭这个文件时,它就把这个ref进行减减操作,由2再变成对应的1,当你再关闭它才由1变成0,然后操作系统才释放它。

【注意事项】

不过如果这个文件是一个普通文件,将来你写的时候数据要定期刷新到磁盘里面,可是今天我们的目的是想让这两个进程,通过对应的缓冲区让他们俩之间通信,好让他们俩直接通信,那么我们的文件呢就不应该把这个数据刷到磁盘上,所以未来呢,我们如果创建了一个文件,这种文件必须有一个特性,就叫做是内存级

【Linux】—— 命名管道详解,Linux,linux,运维,服务器

 【解释说明】  

  •  也就是说对于这种文件只需要把数据有一个进程写进来,另一个进程再从缓冲区中读,此时不需要做这个刷盘动作;
  • 如果做了刷盘操作:一导致速度慢了,二也没必要,所以我们就由此诞生了一种文件,这种文件就叫做管道文件,或者叫做命名管道文件,它就是一个文件,只不过这个文件呢,没有所谓的data block,它就是在磁盘当中的一种

(三)代码示例

3.1命名管道的打开规则

如果当前打开操作是为而打开FIFO时

  • O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
  • O_NONBLOCK enable:立刻返回成功

如果当前打开操作是为而打开FIFO时

  • O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
  • O_NONBLOCK enable:立刻返回失败,错误码为ENXIO
     

3.2 实现server&client通信  

【client.cc】

#include <iostream>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "common.hpp"

int main()
{
    //1. 不需创建管道文件,我只需要打开对应的文件即可!
    int wfd = open(fifoname.c_str(),O_WRONLY);
    if(wfd < 0)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        return 1;
    }

    //正常通信
    char buffer[NUM];
    while(true){
        system("stty raw");
        int c = getchar();
        system("stty -raw");

        ssize_t n = write(wfd, (char*)&c, sizeof(char));
        assert(n >= 0);
        (void)n;
    }

    //关闭不要的fd
    close(wfd);
    return 0;
}

【server.cc】

#include <iostream>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "common.hpp"

int main()
{
    // 1. 创建管道文件
    umask(0); //这个设置并不影响系统的默认配置,只会影响当前进程
    int n = mkfifo(fifoname.c_str(),mode);
    if(n != 0)
    {
        std::cout << errno << " : " << strerror(errno) << std::endl;
        return 1;
    }
    std::cout << "create fifo file success" << std::endl;

    // 2.让服务端直接开启管道文件
    int rfd = open(fifoname.c_str(), O_RDONLY);
    if(rfd < 0 )
    {
        std::cout << errno << " : " << strerror(errno) << std::endl;
        return 2;
    }
    std::cout << "open fifo success" << std::endl;

    // 3.正常通信
    char buffer[NUM];
    while (true)
    {
        buffer[0] = 0;
        ssize_t n = read(rfd,buffer,sizeof(buffer));
        if(n > 0){
            buffer[n] = 0;
            printf("%c", buffer[0]);
            fflush(stdout);
        }
        else if(n == 0){
            std::cout << "client quit, me too" << std::endl;
            break;
        }
        else {
            std::cout << errno << " : " << strerror(errno) << std::endl;
            break;
        }
    }
    
    // 4.关闭不要的fd
    close(rfd);

    unlink(fifoname.c_str());
    return 0;
}

【common.hpp】

#pragma once

#include <iostream>
#include <string>

#define NUM 1024

const std::string fifoname = "./fifo";
uint32_t mode = 0666; 

 (四)小结

以上便是关于命名管道的全部知识内容了,接下来简单小结命名管道以及匿名管道和命名管道之间的区别!!

 命名管道:

  1. 基本概念: 命名管道是一种通过文件系统路径标识的通信管道,允许不同进程之间进行通信。

  2. 创建方式: 在Unix/Linux系统中,可以使用 mkfifo 函数创建命名管道;在Windows系统中,可以使用 CreateNamedPipe 函数。

  3. 通信方向: 命名管道同样是单向的,但可以被用于任意两个进程之间的通信,甚至是不同计算机之间。

  4. 生命周期: 命名管道的生命周期不受限于创建它的进程,可以长时间存在于文件系统中。

  5. 灵活性: 命名管道相对于匿名管道更灵活,适用于更复杂的进程通信场景,包括跨越进程和计算机的通信。

匿名管道与命名管道的区别:

  1.  匿名管道由pipe函数创建并打开。
  2. 命名管道由mkfifo函数创建,打开用open
  3. FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。

本文内容便讲解结束,感谢大家的观看和支持!! 

 【Linux】—— 命名管道详解,Linux,linux,运维,服务器文章来源地址https://www.toymoban.com/news/detail-818199.html

到了这里,关于【Linux】—— 命名管道详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【运维】Linux 跨服务器复制文件文件夹

    如果是云服务 建议用内网ip scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时,用scp可以帮你把文件移出来

    2024年02月08日
    浏览(66)
  • 【Linux运维】shell脚本检查服务器内存和CPU利用率

    在管理服务器时候写了一个 shell脚本,在服务上实现每天凌晨3点查系统的指定文件夹下的容量大小,如果超过10G就要删除3天前的内容,还要时刻查询内存和cpu利用率,如果超过80%就要提示用户出现过载 将以上代码保存为一个.sh文件,然后通过crontab在每天凌晨3点运行即可:

    2024年02月09日
    浏览(65)
  • Linux服务器常见运维性能测试(1)综合跑分unixbench、superbench

    最近需要测试一批服务器的相关硬件性能,以及在常规环境下的硬件运行稳定情况,需要持续拷机测试稳定性。所以找了一些测试用例。本次测试包括在服务器的高低温下性能记录及压力测试,高低电压下性能记录及压力测试,常规环境下CPU满载稳定运行的功率记录。 这个系

    2024年02月04日
    浏览(75)
  • Linux本地部署1Panel服务器运维管理面板并实现公网访问

    1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。高效管理,通过 Web 端轻松管理 Linux 服务器,包括主机监控、文件管理、数据库管理、容器管理等 下面我们介绍在Linux 本地安装1Panel 并结合cpolar 内网穿透工具实现远程访问1Panel 管理界面 执行如下命令一键安装 1Panel: 安

    2024年02月04日
    浏览(92)
  • [1Panel]开源,现代化,新一代的 Linux 服务器运维管理面板

    本期测评试用一下1Panel这款面板。1Panel是国内飞致云旗下开源产品。整个界面简洁清爽,后端使用GO开发,前端使用VUE的Element-Plus作为UI框架,整个面板的管理都是基于docker的,想法很先进。官方还提供了视频的使用教程,本期为大家按照本专栏的基本内容进行多方面的测评。

    2024年02月07日
    浏览(89)
  • 华为云云耀云服务器L实例评测 | Linux系统宝塔运维部署H5游戏

    本章节内容,我们主要介绍华为云耀服务器L实例,从云服务的优势讲起,然后讲解华为云耀服务器L实例资源面板如何操作,如何使用宝塔运维服务,如何使用运维工具可视化安装nginx,最后部署一个自研的H5的小游戏(6岁的小朋友玩的很开心😁)。 前端的同学如果想把自己

    2024年02月07日
    浏览(56)
  • Linux服务器常见运维性能测试(3)CPU测试super_pi、sysbench

    最近需要测试一批服务器的相关硬件性能,以及在常规环境下的硬件运行稳定情况,需要持续拷机测试稳定性。所以找了一些测试用例。本次测试包括在服务器的高低温下性能记录及压力测试,高低电压下性能记录及压力测试,常规环境下CPU满载稳定运行的功率记录。 这个系

    2024年02月02日
    浏览(52)
  • Linux - 进阶 NFS服务器 详解网络共享服务器 ( 预备知识)

               N  :  就是 网络 Network          F   :     就是  File  文件         S   :  system          简称为 网络文件系统                 官方   :               NFS 是一种古老的用于UNIX/LINUX主机之间进行文件共享的协议              Network  File  System 网

    2024年02月13日
    浏览(50)
  • 【Linux】NTP时间服务器Chrony配置详解

    🦄 个人主页——🎐开着拖拉机回家_大数据运维-CSDN博客 🎐✨🍁 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥 🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁🍁🪁🍁🪁 🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🍁🪁🍁🪁🍁 感谢点赞和关注 ,每天

    2024年02月08日
    浏览(38)
  • linux 服务器执行post请求 curl命令详解

    curl是一个命令行访问URL的计算机逻辑语言的工具,发出网络请求,然后得到数据并提取出,显示在标准输出“stdout”上面,可以用它来构造http request报文,curl(CommandLine Uniform Resource Locator),即在命令行中利用URL进行数据或者文件传输。 基本语法: curl [option] [url] 实际用法 PO

    2024年02月02日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包