当前位置: 首页 > news >正文

【Linux】进程间通信:命名管道

Alt

🔥个人主页Quitecoder

🔥专栏linux笔记仓

Alt

目录

    • 命名管道

命名管道

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

命名管道的本质是一个特殊类型的文件,但它不会存储数据,只在内存中维护一个缓冲区,进行先进先出(FIFO)的数据传输

使用 mkfifo() 或 mknod() 在文件系统中创建一个特殊文件。

  • 一个进程以写的方式打开 FIFO,并向其中写入数据。
  • 另一个进程以读的方式打开 FIFO,并从中读取数据。
  • 数据是单向流动的

在这里插入图片描述
命名管道可以从命令行上创建,命令行方法是使用下面这个命令

mkfifo filename

在这里插入图片描述
p开头为管道文件

在这里插入图片描述
在这里插入图片描述
这里的读和写都是阻塞的,管道文件大小一直都是0,因为命名管道数据存储在内存中

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

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

代码实现:首先完成管道生命周期的管理:

namedPipe.hpp文件,提供管道创建和关闭的函数:

#pragma once
#include<iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include<string>
#include<cerrno>
#include<cstdio>
#include<unistd.h>
using namespace std;
const string comm_path ="./myfifo";

int CreateNamedPipe(const string & path)
{
    int res =mkfifo(path.c_str(),0666);
    if(res!=0)
    {
        perror("mkfifo");
    }
    return res;
}
int RemoveNamedPipe(const string & path)
{
    int res =unlink(path.c_str());
    if(res!=0)
    {
        perror("unlink");
    }
    return res;
}

server.cc:

#include"namedPipe.hpp"

int main()
{
    CreateNamedPipe(comm_path);
    RemoveNamedPipe(comm_path);
    return 0;
}

我们这里创建了两个文件,server.cc和client.cc,一定有一个文件来完成管道的创建和删除,这里生成可执行程序就是两个毫无关系的进程

这里可以对上面方法进行封装:

class NamedPipe
{
public:
    NamedPipe(const string &path) : _fifo_path(path)
    {
        int res = mkfifo(path.c_str(), 0666);
        if (res != 0)
        {
            perror("mkfifo");
        }
    }
    ~NamedPipe()
    {
        int res = unlink(_fifo_path.c_str());
        if (res != 0)
        {
            perror("unlink");
        }
    }
private:
    const string _fifo_path;
};

我的主函数直接构建对象即可:

NamedPipe myfifo(comm_path);

管道会自动释放

这里继续在类里面添加其他功能

const string comm_path = "./myfifo";

#define DefaultFd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
class NamedPipe
{
private:
    bool OpenNamedPipe(int mode)
    {
        _fd = open(_fifo_path.c_str(), mode);
        if (_fd < 0)
            return false;
        return true;
    }

public:
    NamedPipe(const string &path, int who) : _fifo_path(path), _id(who), _fd(DefaultFd)
    {
        if (_id == Creater)
        {
            int res = mkfifo(path.c_str(), 0666);
            if (res != 0)
            {
                perror("mkfifo");
            }
        }
    }
    bool OpenForRead()
    {
        OpenNamedPipe(Read);
    }
    bool OpenForWrite()
    {
        OpenNamedPipe(Write);
    }
    ~NamedPipe()
    {
        if (_id == Creater)
        {
            int res = unlink(_fifo_path.c_str());
            if (res != 0)
            {
                perror("unlink");
            }
        }
        if(_fd!=DefaultFd) close(_fd);
    }

private:
    const string _fifo_path;
    int _id;
    int _fd;
};

隐藏打开文件的函数操作,定义宏常量Read和Write两种打开文件方式的mode,初始化传递执行者,是创建者还是使用者来决定构建的时候是否还要再进行管道文件创造

在这里插入图片描述

int ReadNamedPipe(string * out)//输出型参数,输入型const& 输入输出型&
    {
        char buffer[BaseSize];
        int n = read(_fd,buffer,sizeof(buffer));
        if(n>0)
        {
            buffer[n]=0;
            *out = buffer;
        }
        
        return n;
    }
    int WriteNamedPipe(const string & in)
    {
        write(_fd,in.c_str(),in.size());
    }

在这里插入图片描述
在这里插入图片描述

相关文章:

  • Spring(一)
  • Springboot 实用技巧 查缺补漏
  • 3dconvert-viewer.js SDK
  • AI赋能铁道安全巡检探索智能巡检新时代,基于YOLOv7全系列【tiny/l/x】参数模型开发构建铁路轨道场景下轨道上人员行为异常检测预警系统
  • vue通过click和shift实现连续多选功能
  • llama.cpp框架下GGUF格式及量化参数全解析
  • 蓝桥杯备赛-基础练习 day1
  • RAGFlow版本升级-Win10系统Docker
  • tomcat负载均衡配置
  • golang字符串常用的系统函数
  • Linux练级宝典->任务管理和守护进程
  • 基于C语言的简单HTTP Web服务器实现
  • 施磊老师c++笔记(五)
  • 【NLP 33、实践 ⑦ 基于Triple Loss作表示型文本匹配】
  • 计算机网络基础:IIS服务器(FTP服务器)
  • [React Native]Stack、Tab和Drawer导航器详解
  • Node.js Web 模块详解
  • Dockerfile Add和Copy的区别。
  • Amazon RDS ProxySQL 探索(一)
  • C语言数据结构:数组
  • 生态农庄网站模板/手机优化软件下载
  • 制作表白网站教程/seo推广方法集合
  • python做的网站有什么漏洞/怎么开自己的网站
  • 企业宣传片制作公司哪家好/湖南竞价优化哪家好
  • 网站建设主要做什么/公司官网模板
  • 女人和男人做爰有毒网站/ios aso优化工具