进程间通信之命名管道

news2025/2/4 23:53:05

进程间通信之命名管道

  • 命名管道
    • 1.命名管道概念
    • 2.创建一个命名管道
      • 2.1用命名管道实现通信
      • 2.2用命名管道实现server&client通信

命名管道

1.命名管道概念

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

1.什么是命名管道?

命名管道(named pipe)也称为FIFO,它是一种文件类型,创建一个FIFO文件类似于创建一个普通文件。FIFO解决了只有具有亲缘关系的进程间才能通信的问题。并且命名管道是一种特殊类型的文件。

2.匿名管道与命名管道的区别?

  1. 匿名管道由pipe函数创建并打开。
  2. 命名管道由mkfifo函数创建,打开用open
  3. FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义

2.创建一个命名管道

先认识一下mkfifo函数:mkfifo是一个系统调用,用于创建一个命名管道(named pipe),也称为FIFO。
在这里插入图片描述
用mkfifo创建一个管道文件:
在这里插入图片描述
可以看到,管道文件的标志是p,并且大小为零;因为管道文件的数据不需要刷新到磁盘里,所以管道文件的大小一直为零,用vim打开管道文件那就gg。

mkfifo也是一个函数调用,成功返回0,失败返回-1。
,

int mkfifo(const char *pathname, mode_t mode)
返回值int
参数pathname :创建管道的路径。也就是在这个路径下创建一个管道。不带路径,只有文件名,那么默认在当前路径下。
mode_t mode :创建管道的权限。比如0666,0664等,系统下默认掩码umask()=0002。

命名管道的打开规则:

  1. 如果当前打开操作是为读而打开FIFO时
    O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
    O_NONBLOCK enable:立刻返回成功
  2. 如果当前打开操作是为写而打开FIFO时
    O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
    O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

2.1用命名管道实现通信

要求:进程A 向管道当中写 “i am process A”,进程B 从管道当中读 并且打印到标准输出。
进程A代码如下:

#include <iostream>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
using namespace std;

int main()
{
    //1.创建管道文件mkfifo
    umask(0); //这个设置并不影响系统的默认配置,只会影响当前进程
    int n = mkfifo("./fifo", 0666);
    if (n == -1) //失败返回-1,打印错误码并且退出1
    {
        cout << errno << " : " << strerror(errno) << endl;
        return 1;
    }
    //2.让进程A开启管道文件
    int wfd = open("fifo", O_WRONLY);
    if (wfd == -1)//失败返回-1,打印错误码并且退出2
    {
        cout << errno << " : " << strerror(errno) << endl;
        return 2;
    }
    //3.向管道中写入"i am process A"
    while (true)
    {
        char buffer[1024] = "i am process A";
        ssize_t m = write(wfd, buffer, strlen(buffer));
        assert(m > 0);
        (void)m;
        sleep(1);
    }
    close(wfd);
    unlink("fifo");//去掉管道文件的链接,也就是删除fifo文件

    return 0;
}

进程B代码如下:

#include <iostream>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
using namespace std;

int main()
{
    //1.不需创建管道文件,只需要打开对应的文件即可
    int rfd = open("fifo", O_RDONLY);
    if (rfd == -1)//失败返回-1,打印错误码并且退出1
    {
        cout << errno << " : " << strerror(errno) << endl;
        return 1;
    }
    //2.可以进行常规通信了
    while (true)
    {
        char buffer[1024];
        int n = read(rfd, buffer, sizeof(buffer) - 1);
        assert(n >= 0);
        cout << "我是B进程,读取到的数据是:" << buffer << endl;
        sleep(1);
    }
    close(rfd);

    return 0;
}

makefile中代码如下:

.PHONY:all
all:server client

server:server.cc
	g++ -o $@ $^ -std=c++11
client:client.cc
	g++ -o $@ $^ -lncurses -std=c++11 

.PHONY:clean
clean:
	rm -f server client

如果A进程报如下错误:是因为fifo管道文件存在,将fifo文件手动删除即可(rm -f fifo:rm删除文件;-f:强制删除;-r:递归删除,一般用于删除目录等树状结构)。(所以文件末尾需要unlink(“fifo”);//删掉创建的管道文件)
在这里插入图片描述
运行结果如下,可以在B进程看到A进程的消息
在这里插入图片描述

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

要求:client从键盘读入数据,并且发送到管道;server从管道读取数据,并且打印到标准输出。

comm.hpp中代码如下:

#pragma once //防止头文件重复引用

#include <iostream>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define NUM 1024

const std::string fifoname = "./fifo";
uint32_t mode = 0666;

server.cc中代码如下:

#include "comm.hpp"

//少年们, 我刚刚写了一个基于匿名管道的进程池
// 可不可以把它改成使用命名管道呢??
int main()
{
    // 1. 创建管道文件,我们今天只需要一次创建
    umask(0); //这个设置并不影响系统的默认配置,只会影响当前进程
    int n = mkfifo(fifoname.c_str(), mode);
    if(n != 0)
    {
        std::cout << errno << " : " << strerror(errno) << std::endl;
        return 1;
    }
    std::cout << "create fifo file success" << std::endl;
    // 2. 让服务端直接开启管道文件
    int rfd = open(fifoname.c_str(), O_RDONLY);
    if(rfd < 0 )
    {
        std::cout << errno << " : " << strerror(errno) << std::endl;
        return 2;
    }
    std::cout << "open fifo success, begin ipc" << std::endl;

    // 3. 正常通信
    char buffer[NUM];
    while(true)
    {
        buffer[0] = 0;
        ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cout << "client# " << buffer << std::endl;
        }
        else if(n == 0)
        {
            std::cout << "client quit, me too" << std::endl;
            break;
        }
        else 
        {
            std::cout << errno << " : " << strerror(errno) << std::endl;
            break;
        }
    }

    // 关闭不要的fd
    close(rfd);

    unlink(fifoname.c_str());

    return 0;
}

client.cc中代码如下:

#include "comm.hpp"

int main()
{
    //1. 不需创建管道文件,我只需要打开对应的文件即可!
    int wfd = open(fifoname.c_str(), O_WRONLY);
    if(wfd < 0)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        return 1;
    }

    // 可以进行常规通信了
    char buffer[NUM];
    while(true)
    {
        std::cout << "请输入你的消息# ";
        char* msg = fgets(buffer, sizeof(buffer), stdin);
        assert(msg);
        (void)msg;
        
        sleep(1);

        buffer[strlen(buffer) - 1] = 0;
        // abcde\n\0
        // 012345
        if(strcasecmp(buffer, "quit") == 0) break;

        ssize_t n = write(wfd, buffer, strlen(buffer));
        assert(n >= 0);
        (void)n;
    }

    close(wfd);

    return 0;
}

makefile中代码如下:

.PHONY:all
all:server client

server:server.cc
	g++ -o $@ $^ -std=c++11
client:client.cc
	g++ -o $@ $^ -lncurses -std=c++11

.PHONY:clean
clean:
	rm -f server client

运行结果如下:
在这里插入图片描述

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

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

相关文章

高并发的哲学原理(十)-- 理论无限容量:站在地球表面

前面两篇文章每一篇都花了我五十个小时以上&#xff0c;写的我是欲仙欲死&#xff0c;本文我们来务点虚&#xff0c;上上价值。 我们将从微服务架构讲起&#xff0c;一步一步追根溯源&#xff0c;找寻“分布式数据库”在另一个维度的投影&#xff0c;探寻基建、应用、服务、组织…

Java:运算符、位运算 的运算规则与用法详解

目录 运算符Math数学函数与常量类型转换强制类型转换自增和自减运算符关系运算符三元运算符 位运算& 与| 或^ 异或~ 按位取反<< >> 左移 右移运算符优先级 运算符 Math数学函数与常量 import java.lang.Math.*; public class Test{public static void main(S…

java项目之智能仓储系统(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的智能仓储系统。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框架&…

十八、网页端在移动端的像素

一、简介 -1. 在不同的屏幕&#xff0c;单位像素的大小是不同的&#xff0c;像素越小&#xff0c;屏幕越清晰。 手机端的像素就是宽度和高度&#xff0c;如iphone6 4.7寸 750 x 1334。 -2. 手机的像素点 远远小于 计算机的像素点。 问题&#xff1a;一个宽度为900px的网页在i…

探索AI图像安全,助力可信AI发展

探索AI图像安全&#xff0c;助力可信AI发展 0. 前言1. 人工智能发展与安全挑战1.1 人工智能及其发展1.2 人工智能安全挑战 2. WAIC 2023 多模态基础大模型的可信 AI2.1 WAIC 2023 专题论坛2.2 走进合合信息 3. AI 图像安全3.1 图像篡改检测3.2 生成式图像鉴别3.3 OCR 对抗攻击技…

这所211保护一志愿,但复试太难了,考八门课!

一、学校及专业介绍 华中师范大学&#xff08;Central China Normal University&#xff09;&#xff0c;简称“华中师大”&#xff0c;位于湖北省武汉市&#xff0c;是中华人民共和国教育部直属重点综合性师范大学&#xff0c;位列国家“双一流”、“211工程”、“985工程优势…

C++ 在线刷题网站

文章目录 1. 前言2. 效果展示3. 框架4. common4.1 工具类4.2 日志 5. 编译5.1 前言5.2 正文5.3 PathUtil5.4 Compile 6. 运行6.1 限制进程资源6.2 Run 7. 执行7.1 json7.2 Start 参数7.3 FileUtil7.4 Start 8. 启动服务8.1 安装 httplib8.2 compile_server.cpp 9. 测试 compile…

前端学习记录~2023.7.15~CSS杂记 Day7

前言一、介绍 CSS 布局1、正常布局流2、display 属性3、弹性盒子&#xff08;1&#xff09;设置 display&#xff1a;flex&#xff08;2&#xff09;设置 flex 属性 4、Grid 布局&#xff08;1&#xff09;设置 display&#xff1a;grid&#xff08;2&#xff09;在网格内放置元…

吴恩达教授深度学习--神经风格转换算法

什么是神经风格迁移&#xff1f; 假设你有一张内容图片C&#xff08;Content&#xff09;和一张具有独特风格S&#xff08;Style&#xff09;的图片&#xff0c;神经风格迁移可以让这两张图片结合&#xff0c;让原始图片具有图片S的风格。所以神经风格迁移可以解决的问题是&am…

Kafka 入门到起飞系列 - 磁盘存储 -零拷贝

Redis 是 在内存存储数据的&#xff0c;数据读取时不要经过磁盘的IO&#xff0c;只需要内存的操作&#xff0c;这也是redis访问速度快的原因 Kafka背道而驰&#xff0c;Kafka 是在磁盘存储数据的&#xff0c;发送过来的数据交给Kafka后会落盘&#xff0c;消费者读取数据时&…

【C++11】function包装器和bind包装器的简单使用

function function 包装器一些场景下模板的低效性包装器 function 修复问题包装成员函数的注意事项一道例题function包装器的意义 bind 包装器bind 包装器介绍bind 包装器可调整传参顺序bind 包装器可绑定固定参数bind 包装器的意义 C11提供了多个包装器&#xff08;wrapper,也…

BYOVD!干掉EDR/XDR/AVs进程工具

工具介绍 利用gmer驱动程序有效地禁止使用或杀死EDR和AV&#xff0c;它可以流畅地绕过HVCI&#xff1b;该样本来自 loldrivers&#xff1a;https://www.loldrivers.io/drivers/7ce8fb06-46eb-4f4f-90d5-5518a6561f15/ 关注【Hack分享吧】公众号&#xff0c;回复关键字【230614…

docker安装mariadb,并在宿主机连接docker中启动的mariadb

这篇文章主要介绍怎么在docker中安装一个mariadb数据库&#xff0c;然后在我们的电脑本机上连接虚拟机上docker运行的mariadb数据库。 首先&#xff0c;需要安装一个虚拟机软件&#xff0c;通过虚拟机软件安装一个linux操作系统&#xff0c;本篇文章安装的是ubuntu&#xff0c…

一、基础-3、MySQL卸载

1.、停止MySQL服务 winR 打开运行&#xff0c;输入 services.msc 点击 "确定" 调出系统服务。 2. 卸载MySQL相关组件 打开控制面板 ---> 卸载程序 ---> 卸载MySQL相关所有组件。 3. 删除MySQL安装目录 4. 删除MySQL数据目录 数据存放目录是在 C:\ProgramDat…

No.185# 技术管理框架知识点随记

引言 陆续参加了公司组织的两场关于技术管理的培训&#xff0c;时间一长也快忘的七七八八了。本文以刘建国《执行技术人管理之路》为基础框架&#xff0c;将知识点做了整理&#xff0c;在需要的时候翻翻。本文主要内容有&#xff1a; 技术管理之角色认知技术管理之管理规划技术…

【技能实训】DMS数据挖掘项目-Day11

文章目录 任务12【任务12.1】创建用户信息表【任务12.2】在com.qst.dms.entity下创建用户实体类User&#xff0c;以便封装用户数据【任务12.3】在com.qst.dms.service下创建用户业务类UserService【任务12.4】在项目根目录下创建图片文件夹images&#xff0c;存储dms.png【任务…

了解数据科学中的异常检测

大家好&#xff0c;本文将简要介绍一下异常检测&#xff0c;并指导通过不同的技术来识别异常。 如果你正在处理数据&#xff0c;那么无论是现在还是将来&#xff0c;都可能会遇到一项非常重要的任务 —— 异常检测。它在许多领域中都有很大的应用&#xff0c;如制造业、金融和…

visual studio 2017直接打开文件夹时,选择当前项目或者整个解决方案时,按快捷键查找时显示未找到以下指定文本

有的时候只想要打开一整个文件夹来看里面的代码&#xff0c;平时一般用Qt&#xff0c;但是感觉在打开整个文件夹看代码方面&#xff0c;Qt没有VS方便&#xff0c;于是选择了VS&#xff0c;安装的是VS2017&#xff0c;然后发现有个问题&#xff0c;CtrlF查找时&#xff0c;如果选…

报错:Invalid bound statement (not found): com.web.sysmgr.mapper.UserMapper.login

报错&#xff1a;Invalid bound statement (not found): com.web.sysmgr.mapper.UserMapper.login 原因&#xff1a; 确认是否在扫描Mapper接口时指定了正确的包路径。检查 MapperScan 注解中的包路径是否正确&#xff0c;确保只扫描到需要的Mapper接口。 如果在配置类中去配置…

JQuery 实现点击按钮添加 input 框

前言 用于记录开发中常用到的&#xff0c;快捷开发 需求 比如说&#xff0c;我台设备可以设置一个或多个秘钥&#xff0c;有时候我配置一个秘钥时&#xff0c;就不需要多个输入框&#xff0c;当我想配置多个秘钥时&#xff0c;就需要添加多个输入框。 实现 HTML <div…