【Linux】第三十二站:命名管道

news2024/11/16 13:28:45

文章目录

  • 一、命名管道介绍
  • 二、编码
    • 1.mkfifo
    • 2.unlink
    • 3.一个简单的例子
    • 4.修改

一、命名管道介绍

管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。

如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。

命名管道是一种特殊类型的文件

image-20240120181817217

我们可以直接使用下面的命令去创建命名管道

mkfifo myfifo

image-20240120182450551

它的文件类型是以p开头的,也就是命名管道

其实这个myfifo命名管道文件,它在磁盘中并没有数据,它更多的只是一种符号

如下所示

当我们左侧将内容输入到管道的时候,左侧会先进入阻塞。直到右侧使用cat拿到数据以后,左侧才会结束

image-20240120182624167

首先这两个指令是两个进程,这两个进程是毫无关系,但是他们是可以利用这个命名管道进行通信的

也可以看到,在写入的过程中,命名管道的大小一直是0

image-20240120183043910

我们也知道,如果两个不同的进程,打开同一个文件的时候,在内核中,操作系统也是打开一个文件,还是我们前面的这一套

image-20240120210716329

所以:

进程间通信的前提:先让不同的进程看到同一份资源

现在我们的这个管道文件其实就是一个内存级文件,它是不需要刷盘的!

那么我们怎么保证我们两个进程打开的是同一个文件呢?

只要同路径下的同一个文件名即可–>路径 + 文件名具有唯一性

二、编码

1.mkfifo

如下所示

image-20240120212754825

上面的函数可以去创建一个管道文件,第一个参数是路径,第二个是管道的权限是什么,如果成功是0,否则返回-1

如下代码所示

image-20240121123911378

image-20240121123855603

2.unlink

如果我们想要删除一个文件我们可以使用unlink接口

image-20240121124057956

如果成功,返回,如果失败返回-1

如下代码所示

image-20240121124451755

我们可以先编译运行一下,我们会发现会先报错说管道文件已经存在,这是正常的,因为我们之前的并没有删除掉

image-20240121124438918

当我们将原来的管道删除以后,重新运行,就可以看到了

image-20240121125130086

3.一个简单的例子

#pragma once
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string>
#define FIFO_FILE "./myfifo"
#define MODE 0664

enum 
{
    FIFO_CREATE_ERR = 1,
    FIFO_DELETE_ERR,
    FIFO_OPEN_ERR
    
};
using namespace std;
#include "comm.hpp"

int main()
{
    int fd = open(FIFO_FILE,O_WRONLY);
    if(fd < 0)
    {
        perror("clinet open file fail...");
        exit(FIFO_OPEN_ERR);
    }
    cout << "client open success" <<endl;
    string line;
    while(1)
    {
        cout << "Please Enter@ ";
        getline(cin,line);
        write(fd, line.c_str(), line.size());
    }

    close(fd);
    cout << "客户端关闭啦!..." << endl;
    return 0;
}
#include "comm.hpp"
using namespace std;

int main()
{
    //创建一个管道
    int n = mkfifo(FIFO_FILE, MODE);
    if(n == -1) 
    {
        perror("mkfifo");
        exit(FIFO_CREATE_ERR);
    }
    //开始通信
    int fd = open(FIFO_FILE,O_RDONLY);
    if(fd < 0)
    {
        perror("open:");
        exit(FIFO_OPEN_ERR);
    }
    cout <<"server open file sueccess" <<endl;

    while(1)
    {
        char buffer[1024] = {0}; 
        ssize_t x = read(fd, buffer, sizeof(buffer) - 1);
        if(x > 0)
        {
            buffer[x] = 0;
            cout << "服务器收到客户端发送的消息:"<< buffer <<endl;

        }
        else if(x == 0)
        {
            cout << "客户端关闭,服务器关闭" << endl;
            break;
        }
        else 
        {
            break;
        }
    }
    close(fd);
    //关闭信道
    int m = unlink(FIFO_FILE);
    if(m == -1)
    {
        perror("unlink:");
        exit(FIFO_DELETE_ERR);
    }

    return 0;
}

如上代码所示,最终的运行结果为

当我们先打开服务端的时候,我们发现服务端创建了管道,但是并没有打印出server open file success,这说明open处阻塞了

image-20240121153225268

当我们一旦打开了客户端,服务端和客户端几乎同时打开成功。这说明,命名管道文件需要写端和读端都打开的时候才可以,否则只打开其中一个会进入阻塞。我们可以理解为这是为了防止只打开读端,不打开写端的管道会出现读入0的情况。只打开写端,不打开读端会杀掉写端的进程

image-20240121153337884

然后就可以通信了

最终我们我们关闭客户端的同时,由于关闭了写端,但是读端没有关闭,就会读入0,最终服务端的代码逻辑会检测到这个0,从而结束进程

image-20240121153654275

同样的,如果我们先关闭了服务端,那么就会杀掉客户端的进程

image-20240121153931796

4.修改

我们现在对上面的代码进行一下小小的修改,使代码变得更加优雅

如下所示,我们让创建管道和销毁管道变成一个类,这样的话,就不需要我们自己去手动控制了

#pragma once
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string>
#define FIFO_FILE "./myfifo"
#define MODE 0664

enum 
{
    FIFO_CREATE_ERR = 1,
    FIFO_DELETE_ERR,
    FIFO_OPEN_ERR
    
};

class Init
{
public:
    Init()
    {
        //创建一个管道
        int n = mkfifo(FIFO_FILE, MODE);
        if(n == -1) 
        {
            perror("mkfifo");
            exit(FIFO_CREATE_ERR);
        }
    }
    ~Init()
    {
        //关闭信道
        int m = unlink(FIFO_FILE);
        if(m == -1)
        {
            perror("unlink:");
            exit(FIFO_DELETE_ERR);
        }
    }

};

客户端还是不变的

using namespace std;
#include "comm.hpp"

int main()
{
    int fd = open(FIFO_FILE,O_WRONLY);
    if(fd < 0)
    {
        perror("clinet open file fail...");
        exit(FIFO_OPEN_ERR);
    }
    cout << "client open success" <<endl;
    string line;
    while(1)
    {
        cout << "Please Enter@ ";
        getline(cin,line);
        write(fd, line.c_str(), line.size());
    }

    close(fd);
    cout << "客户端关闭啦!..." << endl;
    return 0;
}

下面是服务端,就可以通过一个变量的定义来控制前面的创建管道和关闭管道了

#include "comm.hpp"
using namespace std;

int main()
{
    Init in;
    //开始通信
    int fd = open(FIFO_FILE,O_RDONLY);
    if(fd < 0)
    {
        perror("open:");
        exit(FIFO_OPEN_ERR);
    }
    cout <<"server open file sueccess" <<endl;

    while(1)
    {
        char buffer[1024] = {0}; 
        ssize_t x = read(fd, buffer, sizeof(buffer) - 1);
        if(x > 0)
        {
            buffer[x] = 0;
            cout << "服务器收到客户端发送的消息:"<< buffer <<endl;

        }
        else if(x == 0)
        {
            cout << "客户端关闭,服务器关闭" << endl;
            break;
        }
        else 
        {
            break;
        }
    }
    close(fd);
    return 0;
}

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

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

相关文章

opencv009 滤波器01(卷积)

图像卷积操作&#xff08;convolution&#xff09;&#xff0c;或称为核操作&#xff08;kernel&#xff09;&#xff0c;是进行图像处理的一种常用手段&#xff0c; 图像卷积操作的目的是利用像素点和其邻域像素之前的空间关系&#xff0c;通过加权求和的操作&#xff0c;实现…

【服务器】Xshell与Xftp软件的使用指南

目录 【Xshell软件】 1.1 Xshell软件的功能 1.2 Xshell软件的使用 【Xftp软件】 2.1 Xftp软件的功能 2.2 Xftp软件的使用 可替代产品【FinalShell】 3.1 FinalShell软件的使用 3.2 FinalShell连接服务器失败解决方法 可替代产品【FileZilla】

VSCode无法下载插件,提示 Error while fetching extensions : XHR failed

解决方案&#xff1a; 打开vscode&#xff0c;依次点击File->Preferences->settings&#xff0c;中文就是文件->首选项->设置&#xff0c;打开如下图&#xff1a; 我们去搜索&#xff1a;Proxy &#xff0c; 然后回车 最重要的一步&#xff1a;将Http Prox…

关于 open ai,你了解多少?

OpenAI 的历史 第一阶段&#xff1a;2015-2018 年 2015 年&#xff0c;埃隆马斯克、山姆阿尔特曼、彼得蒂尔和杰西卡利文斯顿联合创立了 OpenAI。OpenAI 的目标是开发安全、有益的 AGI&#xff0c;并确保其造福全人类。在这一阶段&#xff0c;OpenAI 主要专注于基础研究&…

微信公众号怎么申请超过2个

一般可以申请多少个公众号&#xff1f;目前公众号申请数量的规定是从2018年底开始实施的&#xff0c;至今没有变化。规定如下&#xff1a;1、个人可以申请1个个人主体的公众号&#xff1b;2、企业&#xff08;有限公司&#xff09;可以申请2个公众号&#xff1b;3、个体户可以申…

中仕教育:2024年国考面试题型有哪些?

国考面试是选拔公务员的重要环节&#xff0c;通常涉及以下几个方面&#xff1a; 1. 自我介绍&#xff1a;考官通常会要求考生做一个简短的自我介绍。内容可以包括自己的基本情况、学历、工作经历等。 2. 专业知识&#xff1a;根据应聘者所应聘的职位和部门的不同&#xff0c;…

猛玛LARK M1无线麦克风采用 思远半导体 其实就是蓝牙话筒

自上世纪无线电技术开始发展起来&#xff0c;到了几十年后的今天&#xff0c;无线通讯技术已经成熟&#xff0c;开始追求更好的音质以及用户使用体验&#xff0c;优秀的产品也如雨后春笋般的出现&#xff0c;技术革新&#xff0c;极致音质&#xff0c;竞争也越来越激烈。这时候…

VC++中使用OpenCV进行人脸检测

VC中使用OpenCV进行人脸检测 对于上面的图像&#xff0c;如何使用OpenCV进行人脸检测呢&#xff1f; 使用OpenCV进行人脸检测十分简单&#xff0c;OpenCV官网给了一个Python人脸检测的示例程序&#xff0c; objectDetection.py代码如下&#xff1a; from __future__ import p…

【架构师视角系列】Apollo配置中心之Client端(二)

原创文章&#xff0c;转载请标注。https://blog.csdn.net/leeboyce/article/details/135733075 文章目录 声明配置中心系列文章一、客户端架构1、Config Service职责&#xff08;1&#xff09;配置管理&#xff08;2&#xff09;配置发布&#xff08;3&#xff09;配置读取 2、…

【Linux】Linux开发工具 - vim的基本操作

IDE例子 Linux编辑器-vim使用 vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以在终端运行&#xff…

暴力破解常见的服务器

目录 使用 pydictor 生成自己的字典工具liunx下载使用常用的参数说明插件型字典 (可自己根据 API 文档开发) 使用 hydra 工具在线破解系统用户密码使用 hydra 破解 windows 7 远程桌面密码使用 hydra 工具破解 ssh 服务 root 用户密码 使用 Medusa 工具在线破解medusa参数说明M…

公网环境调试本地配置的Java支付宝沙箱环境模拟支付场景

文章目录 前言1. 下载当面付demo2. 修改配置文件3. 打包成web服务4. 局域网测试5. 内网穿透6. 测试公网访问7. 配置二级子域名8. 测试使用固定二级子域名访问 前言 在沙箱环境调试支付SDK的时候&#xff0c;往往沙箱环境部署在本地&#xff0c;局限性大&#xff0c;在沙箱环境…

JVM知识总结

1.概述 JVM指的是Java虚拟机&#xff0c;本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件&#xff0c;作用是为了支持跨平台特性。 功能&#xff1a; 装载字节码&#xff0c;解释/编译为机器码 管理数据存储和垃圾回收 优化热点代码提升效率 …

AI技术图像编辑 Luminar Neo

Luminar Neo是一款先进的AI照片编辑软件&#xff0c;旨在简化和增强照片编辑过程。它适用于macOS和Windows&#xff0c;提供独立的应用程序以及用于集成到现有工作流程的插件。Luminar Neo的主要特点包括AI天空替换、Accent AI、氛围AI以及20多种独特的照片效果。无论是风景摄影…

Qt事件处理,提升组件类

1.相关说明 1.提升组件QLabel的类&#xff0c;以实现双击功能 2.监控键盘事件&#xff0c;实现上下左右移动 3.鼠标点击获取坐标 2.相关界面 3.相关代码和操作 自定义类TMyLabel&#xff0c;父类为QLabel tmylabel.h #ifndef TMYLABEL_H #define TMYLABEL_H #include <QL…

图像处理中,采用极线约束准则来约束特征点匹配搜索空间,理论上在极线上进行搜索。这里的极线是什么线,怎么定义的?基本矩阵F和本质矩阵E有什么区别?

问题描述&#xff1a;图像处理中&#xff0c;采用极线约束准则来约束特征点匹配搜索空间&#xff0c;理论上在极线上进行搜索。这里的极线是什么线&#xff0c;怎么定义的&#xff1f;基本矩阵F和本质矩阵E有什么区别&#xff1f; 问题1解答&#xff1a; 极线是通过极线几何学…

飞书+ChatGPT+cpolar搭建企业智能AI助手并实现无公网ip远程访问

文章目录 推荐 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂…

无线音频设备市场调研:预计2029年将达到404亿美元

无线音频&#xff0c;是指将音频型号以无线电波作为载体&#xff0c;从一个设备传输到另外一个设备&#xff0c;实现音频的无线传输。 最常见的是蓝牙传输&#xff0c;传输频率2.4G&#xff0c;蓝牙音箱、蓝牙耳机都属于蓝牙音频传输&#xff0c;蓝牙音频传输是双向传输&#x…

主板电路学习; 华硕ASUS K43SD笔记本安装win7X64(ventoy)

记录 老爷机 白色 华硕 K43SD 笔记本 安装 win7X64 1. MBR样式常规安装win7X64Sp1 (华硕 K43SD 安装 win7X64 ) 老爷机 白色 华硕 K43SD 笔记本 安装 win7X64 &#xff08;常规安装&#xff09; 设置&#xff1a; 禁用UEFI 启用AHCI ventoy制作MBR&#xff08;非UEFI&#…

性能优化-OpenCL kernel 开发

「发表于知乎专栏《移动端算法优化》」 本文主要介绍OpenCL的 Kernel&#xff0c;包括代码的实例以及使用注意的详解。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&#xff09;开发基础教…