命名管道原理(和匿名管道的对比),mkfifo(命令行,函数),命名管道模拟实现代码+与多个子进程通信代码

news2024/11/24 5:09:19

目录

命名管道

引入

原理

和匿名管道的对比

使用 -- mkfifo

命令行指令

 创建

文件类型p

使用

函数

函数原型

模拟实现

头文件

客户端代码

服务端代码

运行情况

模拟实现 -- 与多个子进程

介绍

服务端代码: 

运行情况


命名管道

引入

匿名管道只能用于父子进程之间通信,如果我们想要两个完全无关联的进程通信该怎么办?

  • 首先,通信本质还是不变的 : 要让不同的进程看到同一份资源
  • 依然还是用文件作为中间介质,但拿到文件的方式不同

原理

  • 如果一个进程打开一个文件,另一个进程也想打开这个文件:
  • 直接让该进程也指向这个已存在的file结构体(不需要再创建一个file,否则内存中会存在大量相同的数据)

  • 但是!普通文件的数据是要被刷新到磁盘上的
  • 我们的目的可不是为了将数据写到磁盘,而是让两个进程进行通信
  • 因此需要尽量避免io(1是 io速度太慢,2是 通信过程产生的数据没必要写到磁盘上)
  • 因此,管道文件油然而生(也就是命名管道),它是一种特殊的文件
  • 它一旦被打开,就会有自己的路径(路径具有唯一性)
  • 因此,不同进程就可以通过唯一的路径来访问同一个管道文件

和匿名管道的对比

两种管道本质上都是一样的(都是文件) 

实现[让不同进程看到同一份资源]的手段不同

  • 匿名管道 -- 子进程继承父进程的文件描述符表,[直接用fd拿到文件]
  • 命名管道 -- 两个进程访问同一路径下的文件,[用路径拿到文件]

使用 -- mkfifo

命令行指令

 创建

文件类型p

p(pipe) -- 管道文件

使用

当只有一个进程打开该管道时,会阻塞

两个不同进程打开同一路径的管道文件(一个命令就是一个进程 ,echo和cat)

就可以进行通信噜

函数

函数原型

模拟实现

头文件

comm.hpp:

#ifndef COMM_H
#define COMM_H

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

using namespace std;

string pipe_path = "./fifo.ipc";
#define mode 0666
#define num 1024

#endif

log.hpp:

#pragma once

#include <iostream>
#include <string>
#include<time.h>

using namespace std;

#define debug 0
#define notice 1
#define warning 2
#define error 3

const string msg[]  //定义不同类型的信息状态
{
    "debug", "notice", "warning", "error"
};

ostream& log(string message,int level) { 
    cout<<"|"<<(unsigned)time(nullptr)<<"|"<<message<<"|"<<msg[level]<<"|"<<endl;
    return cout;
}

客户端代码

#include"comm.hpp"

//用于发送信息(客户端)
int main(){
    //文件操作
    int fd=open(pipe_path.c_str(),O_WRONLY|O_TRUNC);
    if(fd<0){
        perror("open");
        exit(1);
    }
    string buffer;
    while(true){
        cout<<"Please enter the information you want to send : "<<endl;
        getline(cin,buffer);  //输入要发送的信息
        int size=write(fd,buffer.c_str(),buffer.size());//向管道文件写入
        if(size<0){
            perror("write");
            exit(2);
        }
        else if(size==0){
            break;
        }
    } 
    exit(fd);
    return 0;
}

服务端代码

#include "comm.hpp"
#include"log.hpp"

// 用于接收信息(服务端)

int main()
{
    // 创建管道文件
    if (mkfifo(pipe_path.c_str(), mode) < 0)
    {
        perror("mkfifo");
    }
    log("创建管道文件成功",debug);

    // 文件操作
    int fd = open(pipe_path.c_str(), O_RDONLY);
    if (fd < 0)
    {
        perror("open");
        exit(1);
    }
    log("打开文件成功",debug);

    // 进行通信
    char buffer[num];
    while (true)
    {
        memset(buffer, 0, sizeof buffer);
        ssize_t size = read(fd, buffer, sizeof buffer - 1);//读取管道文件中的内容
        cout<<size<<endl;
        if (size < 0)
        {
            perror("read");
            exit(2);
        }
        else if (size == 0)
        {
            cerr << "read end , client quit , sever quit too " << endl;
            break;
        }
        else
        {
            cout << "send_message is : " << buffer << endl;
            log("读取信息成功",debug);
        }
    }

    // 关闭
    close(fd);
    log("关闭管道文件成功",debug);
    unlink(pipe_path.c_str());
    log("删除管道文件成功",debug);
    return 0;
}

运行情况

创建管道,等待另一方打开该管道

一端打开文件后,另一端才打开

服务端收到客户端发送的信息

客户端关闭,服务端也退出当服务端关闭,客户端也会退出

 

模拟实现 -- 与多个子进程

介绍

  • 其他部分与上面相同,只需要在服务端修改
  • 将读取信息的部分分装一个函数
  • 然后在服务端创建子进程,让子进程去读取客户端发送的信息

服务端代码: 

#include "comm.hpp"
#include"log.hpp"

// 用于接收信息(服务端)

void recive_message(int fd){
    char buffer[num];
    while (true)
    {
        memset(buffer, 0, sizeof buffer);
        ssize_t size = read(fd, buffer, sizeof buffer - 1);
        //cout<<size<<endl;
        if (size < 0)
        {
            perror("read");
            exit(2);
        }
        else if (size == 0)
        {
            cerr <<"[ " << getpid() << " ]" << "read end , client quit , sever quit too " << endl;
            break;
        }
        else
        {
            cout << "[ " << getpid() << " ]" <<" send_message is : " << buffer << endl;
            log("读取信息成功",debug);
        }
    }
}
int main()
{
    // 创建管道文件
    if (mkfifo(pipe_path.c_str(), mode) < 0)
    {
        perror("mkfifo");
    }
    log("创建管道文件成功",debug);
    // 文件操作
    int fd = open(pipe_path.c_str(), O_RDONLY);
    if (fd < 0)
    {
        perror("open");
        exit(1);
    }
    log("打开文件成功",debug);
    for(int i=0;i<process_size;i++){
      size_t id=fork();
      if(id==0){
        recive_message(fd); //创建子进程去读取
        exit(0);
      }
    }
    for(int i=0;i<process_size;i++){
      pid_t ret=waitpid(-1,nullptr,0);
    }
    // 关闭
    close(fd);
    log("关闭管道文件成功",debug);
    unlink(pipe_path.c_str());
    log("删除管道文件成功",debug);
    return 0;
}

运行情况

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

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

相关文章

一篇文章带你搞懂DNS全流程

1.DNS与CDN DNS是域名系统的缩写&#xff0c;它是一种将域名和IP地址相互映射的分布式数据库&#xff0c;能够使人更方便地访问互联网。 DNS的主要功能是将域名解析为IP地址。当你在浏览器中输入一个网址时&#xff0c;浏览器会向DNS服务器发送一个请求&#xff0c;以获取该网…

5G-A 商用加速,赋能工业互联网

2019 年 6 月&#xff0c;中国工业和信息化部发放 5G 商用牌照。同年 10 月&#xff0c;三大运营商公布 5G 商用套餐&#xff0c;11 月 1 日正式上线 5G 商用套餐&#xff0c;标志中国正式进入 5G 商用新纪元。今年是 5G 商用的第五年&#xff0c;在当前数字经济蓬勃发展的催化…

什么是屏蔽机房?

屏蔽机房是一种用于保护数据中心设备的安全和可靠的措施。通过屏蔽机房&#xff0c;可以防止电磁干扰、防止物理入侵以及提供更好的隔离和安全性。下面是一些关于屏蔽机房的常见做法&#xff1a; 电磁屏蔽&#xff1a;为了防止电磁干扰对数据中心设备的影响&#xff0c;可以在屏…

代码随想录算法训练营第15天|102. 二叉树的层序遍历226. 翻转二叉树101. 对称二叉树

JAVA代码编写 102. 二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9…

11.8旧有报错与修改

我将uart_done&#xff08;出问题的信号&#xff09;的变量类型设为reg了&#xff0c;也就是我是reg uart_done这个信号的&#xff0c;这样做是错误的&#xff0c;哪怕你在接收模块确实定义的是reg类型&#xff0c;但是在顶层模块的时候&#xff0c;它可以视为是一条单纯的线而…

PPO算法是什么?

ppo称作近邻策略优化算法&#xff0c;是典型的Actor- critic算法&#xff0c;即以两个网络为输入&#xff0c;并可以同时更新两者参数&#xff1b;在RLHF中我们更关注actor网络的更新方式&#xff0c;其损失函数由三部分构成&#xff0c;分别是&#xff1a;1&#xff0c;新旧状…

二进制搭建及高可用 Kubernetes v1.20

目录 一、实验规划&#xff1a; 二、操作系统初始化配置&#xff1a; 1. 关闭防火墙 selinux&#xff1a; 2. 关闭swap分区&#xff1a; 3. 根据规划设置主机名&#xff1a; 4. 所有主机添加hosts&#xff1a; 5. 调整内核参数: 6. 时间同步: 三、部署 etcd 集群&#xff1a…

netty (二) netty原理详解

netty高性能架构设计 netty 写一个简单的demo 服务器端 package com.atguigu.netty.simple;import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import …

GIS开发入门,TopoJSON格式是什么?TopoJSON格式与GeoJSON格式有什么不同?

TopoJSON介绍 TopoJSON是一种几何拓扑结构的地理数据格式,它使用拓扑结构来表示地理对象,可以更有效地压缩和转移数据,从而加快数据加载速度。 TopoJSON格式构成 TopoJSON文件由三部分组成,transform、objects和arcs组成。transform描述了变换参数; objects描述地理实体…

mongodb分组查询

通过userId分组&#xff0c;得到结果字段为&#xff1a;_id和count db.my_solitaire.aggregate([{$group: {_id: "$userId", count: {$sum: 1}}}])通过userId分组得到分组字段和其他想要的字段&#xff0c;得到_id&#xff0c;userName&#xff0c;count userName 为…

【广州华锐互动】智能楼宇3D数字化展示,实现对建筑物的实时监控和管理

随着科技的不断发展&#xff0c;人们对于生活品质的要求也在不断提高。在这个信息爆炸的时代&#xff0c;如何将复杂的数据以直观、生动的方式呈现给用户&#xff0c;已经成为了一个重要的课题。智能楼宇3D数字化展示作为一种新型的建筑科技&#xff0c;正逐渐成为行业的新宠&a…

Spring笔记(三)(Spring整合web环境)

01、Spring整合web环境 1.1 Javaweb三大组件及环境特点 在Java语言范畴内&#xff0c;web层框架都是基于Javaweb基础组件完成的&#xff0c;所以有必要复习一下Javaweb组件的特点 组件作用特点Servlet服务端小程序&#xff0c;负责接收客户端请求并作出响应的单例对象&#…

Lec13 Sleep Wake up

进程切换的流程 一个进程出于某种原因想要进入休眠状态&#xff0c;比如说出让CPU或者等待数据&#xff0c;它会先获取自己的锁&#xff1b;之后进程将自己的状态从RUNNING设置为RUNNABLE&#xff1b;之后进程调用switch函数&#xff0c;其实是调用sched函数在sched函数中再调…

Sealos 私有云正式发布,三倍性能 1/5 成本

马斯克将推特下云后可以节省 60% 成本&#xff0c;不代表你可以。 但是有了 Sealos 之后&#xff0c;你真的可以&#xff01; Sealos 私有云正式发布&#xff0c;详情地址&#xff1a;https://sealos.run/zh-Hans/self-hosting 原文链接&#xff1a;https://forum.laf.run/d/…

使用python操作数据库

一、背景 当前由于多个脚本涉及到账户登陆&#xff0c;同时账号密码存在不断修改的情况&#xff0c;为避免多处修改&#xff0c;现计划将账户信息放到数据库中&#xff0c;后续所有账号信息均从数据库中去读取。 二、本文主要结构 创建测试账户 库表中插入记录 三、代码 1、创建…

【方法】如何取消PDF文件的“打开密码”?

我们知道&#xff0c;PDF文件可以设置“打开密码”&#xff0c;保护文件不被随意打开&#xff0c;那如果后续不需要了&#xff0c;要怎么取消“打开密码”呢&#xff1f;不清楚的小伙伴可以试试小编分享的3种方法&#xff01; 方法1&#xff1a;使用PDF编辑器 PDF编辑器不仅可…

程序员远程兼职接单是骗局?索嘎~

“你还在线上接单&#xff1f;”“没被坑够&#xff1f;”“你不知道这些平台有多坑&#xff1f;”...... 相信无论是有无经验的兄弟都看到过这样的句子。那么事实果真如此吗&#xff1f;今天&#xff0c;带大家来了解一波。 常见的吐槽和问题是&#xff0c;一上来平台还没出力…

域名解析DNS:如何查询txt类型的解析记录

前言 略 查询txt类型的解析记录 使用 nslookup 命令查询。 示例&#xff1a; cmd> nslookup -qttxt _acme-challenge.mydomain.com 服务器: UnKnown Address: fe80::1非权威应答: _acme-challenge.mydomain.com text "_unitrust-dcv2311071423492fmnwb1w…

error: (-215:Assertion failed) !_src.empty() in function ‘cv::cvtColor‘

在给图片去除水印的时候&#xff0c;发现使用cv2打开图片的时候报错了&#xff0c;处理过程中没有找到图片对象&#xff0c;经过分析发现是图片的路径问题导致的&#xff0c;修改路径后未报错

网络安全(黑客)-零基础小白高效自学

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…