命名管道和共享内存

news2024/11/25 2:33:35

命名管道

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

创建命名管道

int main(int argc, char *argv[])
{
 mkfifo("p2", 0644);
 return 0;
}

mkfifo函数可以创建明明管道,第一个参数是指定路径的文件名,第二个参数是创建管道文件的权限

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

匿名函数由pipe函数创建并打开

命名函数由mkfifo函数创建,打开用open

通道一旦建立,那么他们的功能是相似的

用命名管道实现server&client通信

#pragma

#include <iostream>
#include <cstdio>
#include <cerrno>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const std::string comm_path = "./myfifo";

#define DefaultFd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
#define BaseSize 4096

class NamePiped
{
public:
    NamePiped(const std::string& path,int who)
    :_fifo_path(path),_id(who),_fd(DefaultFd)
    {
        if(_id==Creater)
        {
            //服务端创建命名管道
            int res=mkfifo(_fifo_path.c_str(),0666);
            if(res!=0)
            {
                perror("mkfifo");
            }
            std::cout<<" Creater create named pipe "<<std::endl;
        }
    }
    bool OpenForRead()
    {
        return OpenNamedPipe(Read);
    }

     bool OpenForWrite()
    {
        return OpenNamedPipe(Write);
    }

    int ReadNamePipe(std::string* out)
    {
        char buffer[BaseSize];
        int n=read(_fd,buffer,sizeof(buffer));
        if(n>0)
        {
            buffer[n]=0;
            *out=buffer;
        }
        return n;
    }

    int WriteNamePipe(const std::string& in)
    {
        return write(_fd,in.c_str(),in.size());
    }

    ~NamePiped()
    {
        if(_id==User)
        {
            int res=unlink(_fifo_path.c_str());
            if(res!=0)
            {
                perror("unlink");
            }
            std::cout<<" creater free named pipe"<<std::endl;
        }
        if(_fd!=DefaultFd)
        close(_fd);
    }
private:
    bool OpenNamedPipe(int mode)
    {
        _fd = open(_fifo_path.c_str(), mode);
        if (_fd < 0)
        {
            false;
        }
        return true;
    }

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

#include"NamedPipe.hpp"

//read
int main()
{
    NamePiped fifo(comm_path,Creater);
    //对于读端而言,如果我们打开文件,文件还没来,会阻塞在open调用中,知道对方写文件,这也叫进程同步
    //以读方式打开管道文件
    if(fifo.OpenForRead())
    {
        std::cout<<"server open name pipe done"<<std::endl;
        sleep(3);
        while(true)
        {
            std::string message;
            int n=fifo.ReadNamePipe(&message);
            if(n>0)
            {
                std::cout<<"Client Saty> " <<message<<std::endl;
            }
            else if(n==0)
            {
                std::cout<<"Client quit,Server Too!  " <<std::endl;
                break;
            }
            else
            {
                std::cout<<"fifo.ReadNamePipe Error "<<std::endl;
                break;
            }
            
        }
    }
    return 0;

}

#include"NamedPipe.hpp"

//write
int main()
{
    NamePiped fifo(comm_path,User);
    //以写方式打开管道文件
    if(fifo.OpenForWrite())
    {
        std::cout<<"client open name pipe done"<<std::endl;
        while(true)
        {
            //写数据
            std::cout<<"Please Enter>"<<std::endl;
            std::string message;
            std::getline(std::cin,message);
            fifo.WriteNamePipe(message);
        }
    }
    return 0;

}

system V 共享内存

system V 是操作系统中的一种软件接口和系统调用集合的标准

system V 共享内存是一种进程间通信(IPC)机制,他允许多个进程共享一个给定的内存区域,这种通信方式非常高效,因为数据直接在进程间传递,无需数据复制,从而提高了数据传输的效率

我们可以用指令来查看创建的共享内存

ipcs -m

ipcrm -m shmid 删除共享内存

创建共享内存

// 如果没有定义__SHM_HPP__这个宏
#ifndef __SHM_HPP__
// 定义__SHM_HPP__
#define __SHM_HPP__
#include <iostream>
#include <string>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

const int gCreater = 1;
const int gUser = 2;
const std::string gpathname = "/home/ubuntu/lesson16/shm";
const int gproj_id = 0x66; // 随便写的一个数
const int gShmSize = 4096;

class Shm
{
private:
    key_t GetCommKey()
    {
        // pathname:文件路径名,指向系统中的一个现有文件或目录
        // proj_id:项目标识符,通常为一个字符或整数
        key_t k = ftok(_pathname.c_str(), _proj_id);
        if (k < 0)
        {
            perror("ftok");
        }
        return k;
    }
    int GetShmHelper(key_t key, int size, int flag)
    {
        // key:一个 key_t 类型的值,用于标识共享内存段
        // size:共享内存段的大小,以字节为单位,如果指定的 key 已经存在一个共享内存段,那么这个参数将被忽略。
        // shmflg:一组标志位,用于指定共享内存段的权限和其他选项
        // 返回值表示共享内存的标识符
        int shmid = shmget(key, size, flag);
        if (shmid < 0)
        {
            perror("shmget");
        }
        return shmid;
    }
    std::string RoleToString(int who)
    {
        if (who == gCreater)
            return "gCreater";
        else if (who == gUser)
            return "gUser";
        else
            return "None";
    }

    void* AttachShm()
    {
        if(_addrshm!=nullptr)
        {
            DetachShm(_addrshm);
        }
        //shmid:共享内存段的标识符
        //shmaddr:指定共享内存段在调用进程地址空间中的位置。如果设置为 NULL,则由系统选择一个合适的地址进行映射
        //0:映射为可读写(默认)
        //shmat 返回指向共享内存段的指针
        void* shmaddr=shmat(_shmid,nullptr,0);
        if(shmaddr==nullptr)
        {
            perror("shmat");
        }
        std::cout<<"who: "<<RoleToString(_who)<<" attach shm..."<<std::endl;
        return shmaddr;
    }

    void DetachShm(void* shmaddr)
    {
        //shmdt 函数用于从调用进程的地址空间中分离(或“脱离”)一个先前通过 shmat 函数映射的共享内存段。
        //一旦分离,进程将不能再访问该共享内存段
        shmdt(shmaddr);
        std::cout << "who: " << RoleToString(_who) << " detach shm..." << std::endl;
    }

public:
    Shm(const std::string &pathname, int proj_id, int who)
        : _pathname(pathname), _proj_id(proj_id), _who(who), _addrshm(nullptr)
    {
        _key = GetCommKey();
        if (_who == gCreater)
            GetShmUseCreate();
        else if (_who == gUser)
            GetShmForUse();
        _addrshm = AttachShm();

        std::cout << "shmid: " << _shmid << std::endl;
        std::cout << "key: " << ToHex(_key) << std::endl;
    }
    ~Shm()
    {
        if (_who == gCreater)
        {
            // shmid:共享内存标识符,通常通过 shmget 函数获得
            // IPC_RMID:删除共享内存段
            // buf:一个指向 struct shmid_ds 类型结构的指针,该结构包含共享内存段的状态信息,不需要时可以设置为空
            int res = shmctl(_shmid, IPC_RMID, nullptr);
        }
        std::cout << "shm remove done..." << std::endl;
    }

    std::string ToHex(key_t key)
    {
        char buffer[128];
        snprintf(buffer, sizeof(buffer), "0x%x", key);
        return buffer;
    }
    bool GetShmUseCreate()
    {
        // PC_CREAT:如果共享内存段不存在,则创建它。
        // IPC_EXCL:与 IPC_CREAT 一起使用,如果共享内存段已经存在,则 shmget 调用失败。
        // 权限位(如 0600):设置共享内存段的访问权限
        _shmid = GetShmHelper(_key, gShmSize, IPC_CREAT | IPC_EXCL | 0666);
        if (_shmid >= 0)
            return true;

        std::cout << "shm creat done..." << std::endl;
        return false;
    }
    bool GetShmForUse()
    {
        _shmid = GetShmHelper(_key, gShmSize, IPC_CREAT | 0666);
        if (_shmid >= 0)
            return true;

        std::cout << "shm get done..." << std::endl;
        return false;
    }

    void Zero()
    {
        if(_addrshm)
        {
            memset(_addrshm,0,gShmSize);
        }
    }

    void* Addr()
    {
        return _addrshm;
    }

    void DebugShm()
    {
        struct shmid_ds ds;
        int n=shmctl(_shmid,IPC_STAT,&ds);
        if(n<0)return;
        std::cout<<"ds.shm_perm.__key: "<<ToHex(ds.shm_perm.__key)<<std::endl;
        std::cout<<"ds.shm_nattch: "<<ds.shm_nattch<<std::endl;

    }


private:
    key_t _key;
    int _shmid;
    std::string _pathname;
    int _proj_id;
    int _who;
    void *_addrshm;
};

// 条件编译结束
#endif

#include"Shm.hpp"
#include"NamedPipe.hpp"

int main()
{
    // 1. 创建共享内存
    Shm shm(gpathname, gproj_id, gCreater);
    char *shmaddr = (char*)shm.Addr();

    // 2. 创建管道
     NamePiped fifo(comm_path, Creater);
     fifo.OpenForRead();

     while(true)
     {
        std::string temp;
        fifo.ReadNamePipe(&temp);

        std::cout << "shm memory content: " << shmaddr << std::endl;

     }
     //sleep(5);
    return 0;
}
#include"Shm.hpp"
#include"NamedPipe.hpp"
int main()
{
    //1.创建共享内存
    Shm shm(gpathname,gproj_id,gUser);
    //清空_addrshm
    shm.Zero();
    char* shmaddr=(char*)shm.Addr();
    sleep(3);
    //2.打开管道
    NamePiped fifo(comm_path, User);
    fifo.OpenForWrite();

    //当成string
    char ch='A';
    while(ch<='Z')
    {
        shmaddr[ch-'A']=ch;
        std::string temp = "wakeup";
        std::cout << "add " << ch << " into Shm, " << "wakeup reader" << std::endl;
        fifo.WriteNamePipe(temp);
        sleep(1);
        ch++;
    }

    return 0;
}

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

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

相关文章

落地台灯什么牌子好?口碑最好的落地灯品牌

落地台灯什么牌子好&#xff1f;随着落地台灯被越来越多的人认可&#xff0c;如今市场中护眼大路灯品牌类型五花八门&#xff0c;质量存在较大差距。很多网红、明星代言等产品&#xff0c;入行时间短&#xff0c;关注市场营销&#xff0c;而忽视产品核心技术的提升&#xff0c;…

Codeforces Round 982 div2 个人题解(A~D2)

Codeforces Round 982 div2 个人题解(A~D2) Dashboard - Codeforces Round 982 (Div. 2) - Codeforces 火车头 #define _CRT_SECURE_NO_WARNINGS 1#include <algorithm> #include <array> #include <bitset> #include <cmath> #include <cstdio&…

软件系统建设方案书(word参考模板)

1 引言 1.1 编写目的 1.2 项目概述 1.3 名词解释 2 项目背景 3 业务分析 3.1 业务需求 3.2 业务需求分析与解决思路 3.3 数据需求分析【可选】 4 项目建设总体规划【可选】 4.1 系统定位【可选】 4.2 系统建设规划 5 建设目标 5.1 总体目标 5.2 分阶段目标【可选】 5.2.1 业务目…

简记 Vue3(一)—— setup、ref、reactive、toRefs、toRef

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

API网关的作用--为什么微服务需要一个API网关?

微服务网关核心作用就是协议转换、安全隔离和流量控制 微服务架构中&#xff0c;API网关作为系统的入口点&#xff0c;可以统一处理所有客户端请求。 1&#xff09;协议转换&#xff1a;它能够支持多种通信协议&#xff08;如HTTP、gRPC等&#xff09;之间的相互转换&#xff…

【数据结构】快速排序(三种实现方式)

目录 一、基本思想 二、动图演示&#xff08;hoare版&#xff09; 三、思路分析&#xff08;图文&#xff09; 四、代码实现&#xff08;hoare版&#xff09; 五、易错提醒 六、相遇场景分析 6.1 ❥ 相遇位置一定比key要小的原因 6.2 ❥ 右边为key&#xff0c;左边先走 …

一个关于@JsonIgnore的isxxx()问题

一个关于JsonIgnore的问题 版本:2.13.5 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><optional>true</optional></dependency>代码&#xff1a; Data public clas…

2024年10月27日历史上的今天大事件早读

公元前628年10月27日 春秋五霸之一晋文公重耳卒 1915年10月27日 美军进入一战前线 1921年10月27日 思想家严复逝世 1927年10月27日 中共创建井冈山根据地 1937年10月27日 八百壮士坚守四行仓库 1937年10月27日 伪“蒙古联盟自治政府”成立 1938年10月27日 日军对中国军队…

《向量数据库指南》——text-embedding-3-large与Mlivus Cloud打造语义搜索新纪元

使用text-embedding-3-large生成向量并将向量插入Mlivus Cloud实现高效语义搜索的深度解析与实战操作 在数字化时代,数据的处理和存储方式正在经历前所未有的变革。特别是随着大数据和人工智能技术的快速发展,向量数据库作为一种新型的数据存储和查询方式,正逐渐受到越来越…

KUKA机器人选定程序时提示“选择非法”的处理方法

KUKA机器人选定程序时提示“选择非法”的处理方法 如下图所示,选中某个程序,点击选定时, 系统提示:选择非法, 具体处理方法可参考以下内容: 选中该程序后,在右下角打开【编辑】菜单键,再选择【属性】,打开后可以看到程序的一般说明、信息模块和参数等信息,如下图所示…

AMD锐龙8845HS+780M核显 虚拟机安装macOS 15 Sequoia 15.0.1 (2024.10)

最近买了机械革命无界14X&#xff0c;CPU是8845HS&#xff0c;核显是780M&#xff0c;正好macOS 15也出了正式版&#xff0c;试试兼容性&#xff0c;安装过程和之前差不多&#xff0c;这次我从外网获得了8核和16核openCore&#xff0c;分享一下。 提前发一下ISO镜像地址和open…

基于SSH的物流运输货运车辆管理系统源码

基于经典的ssh&#xff08;Spring Spring MVC Hibernate&#xff09;框架与SaaS&#xff08;软件即服务&#xff09;模式&#xff0c;我们为运输企业与物流公司打造了一款开源且易用的车辆管理系统。 该系统主要包含以下核心模块&#xff1a; 档案管理 财务管理 借款管理 保…

研究生论文学习记录

文献检索 检索论文的网站 知网&#xff1a;找论文&#xff0c;寻找创新点paperswithcode &#xff1a;这个网站可以直接找到源代码 直接再谷歌学术搜索 格式&#xff1a;”期刊名称“ 关键词 在谷歌学术搜索特定期刊的关键词相关论文&#xff0c;可以使用以下几种方法&#…

【最全基础知识2】机器视觉系统硬件组成之工业相机镜头篇--51camera

机器视觉系统中,工业镜头作为必备的器件之一,须和工业相机搭配。工业镜头是机器视觉系统中不可或缺的重要组成部分,其质量和性能直接影响到整个系统的成像质量和检测精度。 目录 一、基本功能和作用 二、分类 1、按成像方式分 2、按焦距分 3、按接口类型分 4、按应用…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22目录1. PoisonedRAG: Knowledge corruption attacks to retrieval-augmented generation of large language models摘要创新点…

【数据结构】双指针算法:理论与实战

双指针&#xff08;Two Pointers&#xff09;是一种经典的算法思想&#xff0c;广泛应用于数组、链表等数据结构的处理。该方法通过设置两个指针&#xff0c;在某种规则下移动指针来实现高效的计算与查找。这种算法相比传统的嵌套循环能显著优化时间复杂度&#xff0c;通常能够…

python读取学术论文PDF文件内容

目录 1、PyPDF22、pdfplumber3、PyMuPDF4、pdfminer总结 1、PyPDF2 PyPDF2 是一个常用的库&#xff0c;可以用来读取、合并、分割和修改PDF文件。读取pdf内容&#xff1a; import PyPDF2# 打开PDF文件 with open(ELLK-Net_An_Efficient_Lightweight_Large_Kernel_Network_for…

ThriveX 现代化博客管理系统

ThriveX 现代化博客管理系统 &#x1f389; &#x1f525; 首先最重要的事情放第一 开源不易&#xff0c;麻烦占用 10 秒钟的时间帮忙点个免费的 Star&#xff0c;再此万分感谢&#xff01; 下面开始进入主题↓↓↓ &#x1f308; 项目介绍&#xff1a; Thrive 是一个简而不…

行为设计模式 -责任链模式- JAVA

责任链设计模式 一 .简介二. 案例2.1 抽象处理者(Handler)角色2.2 具体处理者(ConcreteHandler)角色2.3 测试 三. 结论3.1 优缺点3.2 示例3.3 要点 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神…

xxl-job java.sql.SQLException: interrupt问题排查

近期生产环境固定凌晨报错&#xff0c;提示 ConnectionManager [Thread-23069] getWriteConnection db:***,pattern: error, jdbcUrl: jdbc:mysql://***:3306/***?connectTimeout3000&socketTimeout180000&autoReconnecttrue&zeroDateTimeBehaviorCONVERT_TO_NUL…