命名管道的创建和通信实现

目录

命名管道的创建

使用函数创建命名管道的通信

预备创建

makefile设计

server.hpp设计

clent.hpp设计

comm.hpp设计

server.cc设计

clent.cc设计

测试运行


今天我们来学习命名管道

由于匿名管道pipe()无法在两个毫不相干的进程之间进行通信,只能用于 具有亲缘关系的进程(如父子进程、兄弟进程)。如果要让完全独立的进程通信,需要使用 命名管道(FIFO)其他 IPC 机制(如共享内存、消息队列、套接字等)。因为他们彼此不知道管道的名字,不知道名字就无法只读文件名字背后的地址和inode,就进而不知道管道内部存储的信息。关掉有名字不就好了。没错命名管道可以完成不同进程(两个毫不相干进程)间的通信。

命名管道的创建

通信原理和匿名的完全一致,我们可以使用指令或者C语言函数进行创建。

mkfifo 是用于创建 命名管道(FIFO, First In First Out) 的命令或系统调用。这个不是系统函数,是C语言的内置函数,mkfifo xxx(xxx为命名管道的名字),就是直接创建了一个以xxx为名字的命名管道。

使用mkfifo创建了一个命名管道test,然后管道文件的标准就是后面有一个|,我们往里写入是不需要加|的,为了进行进程间的通信,我们需要再打开一个shell,然后有个shell进行写入,另一个看一下这个进程看能不能看到。

可以看到两个毫不相干的进程完成了进程间的通信,不知道你们有没有注意到当一方进行写入时,如果另一方不立刻进行读取,写的一方会卡住,因为命名管道(FIFO)同步的写端(echo)必须等待读端(cat 或其他进程)来读取数据,否则写操作会阻塞。就是不允许一直写而不读,终归来说就是写端这个进行一直保持挂起状态而不退出,这个是放在前提进行的特点,我们出现这种情况,要么就是另一端进行读取,要么就是将写入放到后端进行。

如上图可知,当程序处于后端后:

使用函数创建命名管道的通信

预备创建

使用命名管道进行通信,需要使用C语言函数mkfifo

mkfifo的第一个参数是创建管道的路径(包括文件名),第二个参数是管道的使用权限,返回值为0表示创建成功,-1表示失败,然后需要形成两个可执行程序,代表两个毫不相干的进程进行通信,然后编写makefile,同时编译两个进程。

所以很简单,我们定义clent,server两个进程,然后分别创建各自的.cc和.hpp,然后comm.hpp是两个进程的共有部分,都能相互看到的内容。让两个可执行程序的.hpp都引用头文件comm.hpp。

最后销毁管道我们使用函数unlink销毁管道,这个函数就只需要传递管道的路径,然后返回值如果是0就是销毁成功,-1就是销毁失败。但是这个函数不是真的去把管道删除了,只是删除了管道的名字和inode的映射关系,只是删除了管道的路径,一个文件没有了路径之前说了就没有存在的必要了,这样就会被操作系统给释放了。

接下来的设计我就不会明说了,因为都很简单!!!

makefile设计

为了同时可以编译两个可执行文件,需要重新定义一个伪目标all,然后让其依赖两个可执行,没有依赖方法,这样就可以了在预编译all的时候编译了server和clent。

server.hpp设计

#pragma once
#include"comm.hpp"
class Init
{
public:
    Init()
    {
        umask(0);
        int n = ::mkfifo(pipefile.c_str(), gmode);
        if (n < 0)
        {
            cerr << "mkfifo error!" << endl;
            return;
        }
        cout << "mkfifo success" << endl;
        sleep(10);

    }
    ~Init()
    {
        int n = unlink(pipefile.c_str());
        if (n < 0)
        {
            cerr << "unlink error!" << endl;
            return;
        }
        cout << "unlink success" << endl;
    }
};

Init init;

class server
{
public:
    server()
    :_fd(gdefultfd)
    {}
    bool openpipe()
    {
        _fd = ::open(pipefile.c_str(), O_RDONLY);
        if (_fd < 0)
        {
            cerr << "open fail!" << endl;
            return false;
        }
        return true;
    }
    //string* :输出型参数
    //const string& :输入型参数
    //string & : 输入输出型参数
    int recpipe(string* out) //server负责读取
    {
        char buffer[gsize];
        ssize_t n = ::read(_fd, buffer, sizeof(buffer)-1);
        if (n > 0)
        {
            buffer[n] = 0;
            *out = buffer;
        }
        return n;
    }
    void closepipe()
    {
        if (_fd >= 0)
        {
            ::close(_fd);
        }
    }
    ~server()
    {
        //closepipe();
    }
private:
    int _fd;
};

由于需要通信的所以需要先有一个进程先来创建这个管道,我们先让进程server来创建这个命名管道,如上封装在Init类里,然后像gmode(管道权限),pipefile(路径),gdefultfd(文件描述符的初始值),gsize(读取容量),都是放在了comm.hpp里面作为共有资源被看到。

server我们让其负责读数据的工作,所以以读的形式打开,然后repipe中read读到输出型参数out里面,然后out将来以引用传入,再打印出来就可以了。

然后这里为了使读入的是字符串是/0不被读取,不然会乱码而少读取一个字节,然后将最后一位的下一个置为0,使读入缓冲区时可以刷新。

clent.hpp设计

#pragma once
#include"comm.hpp"
class clent
{
public:
    clent()
    :_fd(gdefultfd)
    {}
    bool openpipe()
    {
        _fd = ::open(pipefile.c_str(), O_WRONLY);
        if (_fd < 0)
        {
            cerr << "open fail!" << endl;
            return false;
        }
        return true;
    }
    //string* :输出型参数
    //const string& :输入型参数
    //string & : 输入输出型参数
    int sendpipe(string& in) //server负责读取
    {
        return ::write(_fd, in.c_str(), in.size());
    }
    void closepipe()
    {
        if (_fd >= 0)
        {
            ::close(_fd);
        }
    }
    ~clent()
    {
        //closepipe();
    }
private:
    int _fd;
};

clent进程就负责写入管道了,以只写打开管道后使用write直接写入就可以了。其他和server都一样的。

comm.hpp设计

这部分就是进程间可以看到的公共的部分了,我们可能会质疑到这个gsize有范围,那我一次写入如果超过,那一次读取不就读取不完了吗,那剩余的怎么办?剩下没有读取的就会留到下一次读取的时候再读,这样相当于将单次读取拆开了。

server.cc设计

#include"server.hpp"
int main()
{
    server ser;
    ser.openpipe();
    string message;
    while (true)
    {
        if (ser.recpipe(&message) > 0)
        {
            cout << "clent say# " << message << endl;
        }
        else
        {
            break;
        }
    }
    cout << "clent quit, me too " << endl;
    ser.closepipe();
    return 0;
}

就是执行打开,读取,然后关闭。

clent.cc设计

#include"clent.hpp"
int main()
{
    clent cle;
    cle.openpipe();
    string message;
    while(true)
    {
        cout << "please enter: ";
        getline(cin, message);
        cle.sendpipe(message);
    }
    cle.closepipe();
    return 0;
}

就是依次执行打开,写入,关闭。

测试运行

如果已经存在管道fifo需要先删除,我们需要先让读端打开,然后再写入,这样比较合理,防止写入的信息读不到。

可以看到,写端正常写入的同时,读端正常读取,写端退出时读端由于没有可读的了,就也跟着退出并将管道销毁了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

密码学 网络安全 科普 网络安全密码技术

网络加密包括密码技术和网络加密方法两个方面。 一、 密码技术   密码技术一般分为常规密码和公钥密码。   常规密码是指收信方和发信方使用相同的密钥&#xff0c;即加密密钥和解密密钥是相同或等价的。比较著名的常规密码算法有DES及其各种变形、IDEA、FEAL、Skipjack…

LLM run

lmstudio lmstudio ollama ollama N 卡使用自带UI gpu加速推理 ,选择满足条件的&#xff0c; ds模型选择列表 https://ollama.com/library/deepseek-r1 a卡当前支持的显卡型号 I卡 gpu加速配置 2025.3 intel Official project optimization https://www.modelscope.cn/m…

[Java]使用java进行JDBC编程

首先要从中央仓库下载api(类似驱动程序)&#xff0c;为了链接java和mysql 下载jar包&#xff0c;需要注意的是jar包的版本要和mysql保持一致 下面是新建文件夹lib&#xff0c;把jar包放进去&#xff0c;并添加为库 sql固定的情况下运行 import com.mysql.cj.jdbc.MysqlDataSo…

小程序事件系统 —— 32 事件系统 - 事件分类以及阻止事件冒泡

在微信小程序中&#xff0c;事件分为 冒泡事件 和 非冒泡事件 &#xff1a; 冒泡事件&#xff1a;当一个组件的事件被触发后&#xff0c;该事件会向父节点传递&#xff1b;&#xff08;如果父节点中也绑定了一个事件&#xff0c;父节点事件也会被触发&#xff0c;也就是说子组…

某些网站访问很卡 or 力扣网站经常进不去(2025/3/10)

很早之前就感觉力扣很卡&#xff0c;但是以为很正常&#xff0c;今天偶然感觉很不对劲&#xff0c;其他网站都能打开&#xff0c;就力扣打不开&#xff0c;很烦人&#xff0c;这里还是记录一下&#xff08;截止 2025/3/10 方法有效&#xff09;。 问题原因 DNS解析错误&#x…

【网络安全工程】任务10:三层交换机配置

CSDN 原创主页&#xff1a;不羁https://blog.csdn.net/2303_76492156?typeblog三层交换机是指在OSI&#xff08;开放系统互连&#xff09;模型中的第三层网络层提供路由功能的交换机。它不仅具备二层交换机的交换功能&#xff0c;还能实现路由功能&#xff0c;提供更为灵活的网…

SpringMVC-全局异常处理

文章目录 1. 全局异常处理2. 项目异常处理方案2.1 异常分类2.2 异常解决方案2.3 异常解决方案具体实现 1. 全局异常处理 问题&#xff1a;当我们在SpingMVC代码中没有对异常进行处理时&#xff0c;三层架构的默认处理异常方案是将异常抛给上级调用者。也就是说Mapper层报错会将…

天津大学:《深度解读DeepSeek:部署、使用、安全》

大家好&#xff0c;我是吾鳴。 吾鳴之前给大家分享过由天津大学出品的报告《DeepSeek原理与效应》&#xff0c;今天吾鳴再给大家分享一份由天津大学出品的报告——《深度解读DeepSeek&#xff1a;部署、使用、安全》。 报告主要从DeepSeek本地化部署、DeepSeek使用方法与技巧、…

Dagger 2 系列(五)——进阶之@Scope 和 @Singleton

前言&#xff1a; 在上一篇Dagger 2 系列&#xff08;四&#xff09;——Named 和 Qualifier注解介绍&#xff0c;了Named 和 Qualifier注解&#xff0c;这篇文章&#xff0c;我们将会了解另外俩个注解&#xff1a;Scope 和 Singleton。 在这篇文章中你会了解到&#xff1a; …

STM32初始安装

前言 很多人刚买来STM32就迫不及待地想要用它来写程序&#xff0c;看见STM32开发版和ST-Link上有几个插口就直接连接&#xff0c;结果就像我一样一不小心就导致ST -Link烧坏了&#x1f602; 所以本篇博客将做最基础的但是对于小白来说最重要的教学&#xff0c;STM32的线路连接…

爱普生温补晶振 TG5032CFN高精度稳定时钟的典范

在科技日新月异的当下&#xff0c;众多领域对时钟信号的稳定性与精准度提出了极为严苛的要求。爱普生温补晶振TG5032CFN是一款高稳定性温度补偿晶体振荡器&#xff08;TCXO&#xff09;。该器件通过内置温度补偿电路&#xff0c;有效抑制环境温度变化对频率稳定性的影响&#x…

深入理解C语言链表:数据结构的基石

在C语言的编程宇宙中&#xff0c;链表就像是一座稳固的基石&#xff0c;支撑着众多复杂程序的构建。它以独特的魅力和强大的功能&#xff0c;在解决各类编程难题时发挥着至关重要的作用。今天&#xff0c;就让我们一同深入探索链表的奥秘。 目录 一、链表初相识 二、链表的结…

从头开始开发基于虹软SDK的人脸识别考勤系统(python+RTSP开源)(二)

今天咱们继续昨天的话题&#xff0c;今天的重点是看思路和代码了。废话不多说&#xff0c;直接上干货。 先说一句&#xff0c;为了省事&#xff0c;直接一个文件完成所有功能&#xff0c;可能在代码可读性上差一些&#xff0c;比较眼花缭乱哈哈。整个文件含空行代码共1931行&a…

报表控件stimulsoft操作:使用 Angular 应用程序的报告查看器组件

Stimulsoft Ultimate &#xff08;原Stimulsoft Reports.Ultimate&#xff09;是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能&#xff0c;Stimulsoft Ultimate包含了…

【网络编程】WSAAsyncSelect 模型

十、基于I/O模型的网络开发 接着上次的博客继续分享&#xff1a;select模型 10.8 异步选择模型WSAAsyncSelect 10.8.1 基本概念 WSAAsyncSelect模型是Windows socket的一个异步I/O 模型&#xff0c;利用这个模型&#xff0c;应用程序 可在一个套接字上接收以Windows 消息为基…

从0开始的操作系统手搓教程43——实现一个简单的shell

目录 添加 read 系统调用&#xff0c;获取键盘输入 :sys_read putchar和clear 上班&#xff1a;实现一个简单的shell 测试上电 我们下面来实现一个简单的shell 添加 read 系统调用&#xff0c;获取键盘输入 :sys_read /* Read count bytes from the file pointed to by fi…

鸿蒙应用开发—数据持久化之SQLite

文章目录 SQLite简介创建数据库添加数据查询数据更新数据删除数据升级数据库使用事务参考 SQLite简介 SQLite是一个轻量级关系数据库&#xff0c;占用资源很少&#xff0c;只有几百KB的大小&#xff0c;无需服务器支撑&#xff0c;是一个零配置、事务性的SQL数据库引擎。 相对…

应急响应--流量分析

&#xff08;一&#xff09;Cobalt Strike流量特征分析 1.HTTP特征 源码特征&#xff1a; 在流量中&#xff0c;通过http协议的url路径&#xff0c;在checksum8解密算法计算后&#xff0c;32位的后门得到的结果是92&#xff0c;64位的后门得到的结果是93&#xff0c;该特征符…

初始化E9环境,安装Sqlserver数据库

title: 初始化E9环境,安装Sqlserver数据库 date: 2025-03-10 19:27:19 tags: E9SqlServer初始化E9环境,安装Sqlserver数据库 安装E9本地环境安装Sql server 数据库1、检查SQL Server服务是否开启2、检查SQL Server网络网络配置是否开启创建一个ecology数据库点击初始化数据库…

自然语言处理:无监督朴素贝叶斯模型

介绍 大家好&#xff0c;博主又来和大家分享自然语言处理领域的知识了&#xff0c;今天给大家介绍的是无监督朴素贝叶斯模型。 在自然语言处理这个充满挑战又极具魅力的领域&#xff0c;如何从海量的文本数据中挖掘有价值的信息&#xff0c;一直是研究者们不断探索的课题。无…