命名管道:简单案例实现

📟作者主页:慢热的陕西人

🌴专栏链接:Linux

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

本博客主要内容讲解了什么是命名管道,匿名管道和命名管道的区别,并且实现了一个案例来实践操作

文章目录

  • Linux命名管道
    • 1.概念
    • 2.创建一个命名管道
    • 3.匿名管道与命名管道的区别
    • 4.我们实现一个即时的输入输出
    • 5.完整代码

Linux命名管道

1.概念

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

2.创建一个命名管道

  • 命名管道可以从命令行上创建,命令行方法是使用下面这个命令 :

    mkfifo filename

    image-20231128174723565

    见见猪跑:

    向管道写入:echo hello > fifo:我们发现程序卡住了,细节是我们查看fifo的文件的大小的时候,它却是0,因为我们知道管道是内存级文件,他的内容不会刷新到磁盘,所以我们看到的文件大小就是0,当我们cat < fifo也就是将fifo中的内容重定向输出到cat中打印出了hello

image-20231128193005159

那么上面的操作,是通过一个管道文件,让两个无关的进程实现的进程间的通信。那么我们知道进程间的通信就是要让两个进程看到同一个文件,那么这里我们是如何做到同一个文件呢?答案是路径,文件的唯一性就是由路径表示的!


那么我们到底是如何使用命名管道实现两个进程间的通信的:

①我们需要创建一个管道文件

这里我们需要用到一个系统接口mkfifo

image-20231128204130327

#include<iostream>
#include<sys/stat.h>
#include<sys/types.h>
#include<string.h>
#include<cerrno>#include "comm.hpp"using namespace std;
int main()
{
//1.创建管道文件,我们今天只需要创建一次
int n  = mkfifo(filename.c_str(),mode);
if(n != 0) //创建失败
{cout << errno << " : "<< strerror(errno)<<  endl;return 1;
}return 0;
}

运行一下:

我们发现确实创建了文件:但是文件的权限却不是我们想要的0666,其实我们一下就能看出来原因是我们的umask不为零影响到了结果

image-20231128204311535

我们查看一个操作系统的接口:umask

image-20231128204715405

#include<iostream>
#include<sys/stat.h>
#include<sys/types.h>
#include<string.h>
#include<cerrno>#include "comm.hpp"using namespace std;
int main()
{
//1.创建管道文件,我们今天只需要创建一次
umask(0); //只影响当前进程的umask
int n  = mkfifo(filename.c_str(),mode);
if(n != 0) //创建失败
{cout << errno << " : "<< strerror(errno)<<  endl;return 1;
}return 0;
}

运行一下看看:
image-20231128204930740

②让读写端进程分别按照自己的需求打开文件

 //1.不需要创建管道文件,我只需要打开对应的文件即可!int wfd = open(filename.c_str(), O_WRONLY);if(wfd < 0){cerr << errno << " : "<< strerror(errno)<<  endl;return 1;}//1.创建管道文件,我们今天只需要创建一次umask(0); //只影响当前进程的umaskint n  = mkfifo(filename.c_str(),mode);if(n != 0) //创建失败{cout << errno << " : "<< strerror(errno)<<  endl;return 1;}

③开始通信

//3.开始通信char buffer[NUM];while(true){buffer[0] = 0; //初始化第一个位置为\0//读文件ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);if(n > 0){//读成功了buffer[n] = 0;printf("%s\n", buffer);fflush(stdout);}else if(n == 0){//写端关闭cout << "client quit, me too" << endl;break;}else{//错误cout << errno << " : "<< strerror(errno)<<  endl;return 1;}}//2.开始通信char buffer[NUM];while(true){cout << "请输入要写入的信息#";char* msg = fgets(buffer, sizeof(buffer), stdin);assert(msg);(void)msg;buffer[strlen(buffer) - 1] = 0;//当我们写入quit的时候退出写端if(strcasecmp(buffer, "quit") == 0) break;ssize_t n = write(wfd, buffer, strlen(buffer));assert(n >= 0); (void)n;}

运行结果:

image-20231128223524668

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

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

4.我们实现一个即时的输入输出

就是我们输入管道的时候不用回车,而是选用输入一个字符就从管道输出:

我们要在client.cc端改变其向文件写入的方式,我们读取到字符c中,然后没输入一个字符就同步;

    while(true){system("stty raw");  // 使终端驱动处于一次一字符模式char c = getchar();system("stty cooked");// 使终端驱动回到一次一行模式 ssize_t n = write(wfd, &c, sizeof(char));assert(n >= 0); (void)n;}

运行结果:

打印结果

5.完整代码

client.cc

#include<iostream>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include<cerrno>
#include<cassert>
#include"comm.hpp"using namespace std;
int main()
{//1.不需要创建管道文件,我只需要打开对应的文件即可!int wfd = open(filename.c_str(), O_WRONLY);if(wfd < 0){cerr << errno << " : "<< strerror(errno)<<  endl;return 1;}//2.开始通信char buffer[NUM];while(true){// cout << "请输入要写入的信息#";// char* msg = fgets(buffer, sizeof(buffer), stdin);// assert(msg);// (void)msg;// buffer[strlen(buffer) - 1] = 0;system("stty raw");  // 使终端驱动处于一次一字符模式char c = getchar();system("stty cooked");// 使终端驱动回到一次一行模式 // //当我们写入quit的时候退出写端// if(strcasecmp(buffer, "quit") == 0) break;ssize_t n = write(wfd, &c, sizeof(char));assert(n >= 0); (void)n;}return 0;
}

server.cc

#include<iostream>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include<cerrno>#include "comm.hpp"using namespace std;
int main()
{//1.创建管道文件,我们今天只需要创建一次umask(0); //只影响当前进程的umaskint n = mkfifo(filename.c_str(),mode);if(n != 0) //创建失败{cout << errno << " : "<< strerror(errno)<<  endl;return 1;}cout << "创建文件成功!"<< endl;//2.打开文件int rfd = open(filename.c_str(), O_RDONLY);if(rfd < 0) //打开错误{cout << errno << " : "<< strerror(errno)<<  endl;return 2;}cout << "打开管道成功" << endl;//3.开始通信char buffer[NUM];while(true){buffer[0] = 0; //初始化第一个位置为\0//读文件ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);if(n > 0){//读成功了printf("%c", buffer[0]);fflush(stdout);}else if(n == 0){//写端关闭cout << "client quit, me too" << endl;break;}else{//错误cout << errno << " : "<< strerror(errno)<<  endl;return 1;}}//4.关闭文件close(rfd);unlink(filename.c_str());return 0;
}

comm.hpp

#pragma once#include <iostream>
#include <string>using namespace std;#define NUM 65535 //管道缓冲区大小string filename = "./fifo"; //文件名
mode_t mode = 0666; //打开方式

到这本篇博客的内容就到此结束了。
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正

在这里插入图片描述

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

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

相关文章

【GraphQL 】将GraphQL API添加到Postgres数据库的六种简单方法,比较Hasura、Prisma和其他

PostgreSQL是世界上最流行的开源SQL数据库之一&#xff0c;GraphQL是一种日益流行的API规范。 将经过验证和众所周知的PostgreSQL与GraphQL带来的API创建新方式集成在一起不是很好吗&#xff1f; 在本文中&#xff0c;我们讨论了六个不同的项目&#xff0c;它们试图将SQL与Gr…

深入了解Rabbit加密技术:原理、实现与应用

一、引言 在信息时代&#xff0c;数据安全愈发受到重视&#xff0c;加密技术作为保障信息安全的核心手段&#xff0c;得到了广泛的研究与应用。Rabbit加密技术作为一种新型加密方法&#xff0c;具有较高的安全性和便捷性。本文将对Rabbit加密技术进行深入探讨&#xff0c;分析…

【动态规划】LeetCode-面试题08.01三步问题

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…

六、初识FreeRTOS之FreeRTOS的任务挂起和恢复函数介绍

本节需要掌握以下内容&#xff1a; 1&#xff0c;任务的挂起与恢复的API函数&#xff08;熟悉&#xff09; 2&#xff0c;任务挂起与恢复实验&#xff08;掌握&#xff09; 3&#xff0c;课堂总结&#xff08;掌握&#xff09; 一、任务的挂起与恢复的API函数&#xff08;熟…

exceljs读取el-upload上传的excle数据并转为json输出

当使用 Element UI 的 el-upload 组件上传 Excel 文件时&#xff0c;您可以使用 exceljs 库将上传的 Excel 数据转换为 JSON 格式。以下是一个示例代码&#xff0c;演示了如何在 Vue 项目中实现这一功能&#xff1a; <template><el-uploadclass"upload-demo&quo…

C++ day41 动态规划 整数拆分 不同的二叉搜索树

题目1&#xff1a;343 整数拆分 题目链接&#xff1a;整数拆分 对题目的理解 将正整数n&#xff0c;拆分成k个正整数的和&#xff08;k>2&#xff09;使得这些整数的乘积最大化&#xff0c;返回最大乘积 动规五部曲 1&#xff09;dp数组的含义以及其下标i的含义 dp[i]…

Verilog 入门(四)(门电平模型化)

文章目录 内置基本门多输入门简单示例 内置基本门 Verilog HDL 中提供下列内置基本门&#xff1a; 多输入门 and&#xff0c;nand&#xff0c;or&#xff0c;nor&#xff0c;xor&#xff0c;xnor 多输出门 buf&#xff0c;not 三态门上拉、下拉电阻MOS 开关双向开关 门级逻辑…

OSG编程指南<十七>:OSG光照与材质

1、OSG光照 OSG 全面支持 OpenGL 的光照特性&#xff0c;包括材质属性&#xff08;material property&#xff09;、光照属性&#xff08;light property&#xff09;和光照模型&#xff08;lighting model&#xff09;。与 OpenGL 相似&#xff0c;OSG 中的光源也是不可见的&a…

工博会新闻稿汇总

23届工博会媒体报道汇总 点击文章标题即可进入详情页 9月23日&#xff0c;第23届工博会圆满落幕&#xff01;本届工博会规模之大、能级之高、新展品之多创下历史之最。高校展区在规模、能级和展品上均也创下新高。工博会系列报道深入探讨了高校科技发展的重要性和多方面影响。…

【合集】MQ消息队列——Message Queue消息队列的合集文章 RabbitMQ入门到使用

前言 RabbitMQ作为一款常用的消息中间件&#xff0c;在微服务项目中得到大量应用&#xff0c;其本身是微服务中的重点和难点。本篇博客是Message Queue相关的学习博客文章的合集篇&#xff0c;目前主要是RabbitMQ入门到使用文章&#xff0c;后续会扩展其他MQ。 目录 前言一、R…

自定义链 SNAT / DNAT 实验举例

参考原理图 实验前的环境搭建 1. 准备三台虚拟机&#xff0c;定义为内网&#xff0c;外网以及网卡服务器 2. 给网卡服务器添加网卡 3. 将三台虚拟机的防火墙和安全终端全部关掉 systemctl stop firewalld && setenforce 0 4. 给内网虚拟机和外网虚拟机 yum安装 httpd…

阿里云国际短信业务网络超时排障指南

选取一台或多台线上的应用服务器或选取相同网络环境下的机器&#xff0c;执行以下操作。 获取公网出口IP。 curl ifconfig.me 测试连通性。 &#xff08;推荐&#xff09;执行MTR命令&#xff08;可能需要sudo权限&#xff09;&#xff0c;检测连通性&#xff0c;执行30秒。 m…

【华为OD题库-052】数字序列比大小-java

题目 A&#xff0c;B两个人玩一个数字比大小的游戏&#xff0c;在游戏前&#xff0c;两个人会拿到相同长度的两个数字序列&#xff0c;两个数字序列是不完全相同的&#xff0c;且其中的数字是随机的。 A&#xff0c;B各自从数字序列中挑选出一个数字进行大小比较&#xff0c;赢…

Scrapy框架中间件(一篇文章齐全)

1、Scrapy框架初识&#xff08;点击前往查阅&#xff09; 2、Scrapy框架持久化存储&#xff08;点击前往查阅&#xff09; 3、Scrapy框架内置管道&#xff08;点击前往查阅&#xff09; 4、Scrapy框架中间件 Scrapy 是一个开源的、基于Python的爬虫框架&#xff0c;它提供了…

HashMap的实现原理

1.HashMap实现原理 HashMap的数据结构&#xff1a; *底层使用hash表数据结构&#xff0c;即数组链表红黑树 当我们往HashMap中put元素时&#xff0c;利用key的hashCode重新hash计算出当前对象的元素在数组中的下标 存储时&#xff0c;如果出现hash值相同的key&#xff0c;此时…

自动化测试 —— 如何优雅实现方法的依赖!

在 seldom 3.4.0 版本实现了该功能。 在复杂的测试场景中&#xff0c;常常会存在用例依赖&#xff0c;以一个接口自动化平台为例&#xff0c;依赖关系&#xff1a; 创建用例 --> 创建模块 --> 创建项目 --> 登录。 用例依赖的问题 •用例的依赖对于的执行顺序有严格…

SpringBoot——Spring Security 框架

优质博文&#xff1a;IT-BLOG-CN 一、Spring Security 简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的 Bean&#xff0c;充分利用了Spring IoC&#xff0c;DI&#xff0…

什么是 Proxy?

目录 Proxy 的作用 1. 流量过滤 2. 记录日志 3. 加快访问速度 4. 隐藏 IP 地址 Proxy 的分类 1. 按协议分类 - HTTP 代理&#xff1a;只支持 HTTP 协议的代理服务器&#xff0c;它可以缓存 HTTP 请求和响应并过滤 HTTP 流量。 - FTP 代理&#xff1a;只支持 FTP 协议的…

异常数据检测 | Python实现孤立森林(IsolationForest)异常检测

孤立森林(IsolationForest)异常检测 IsolationForest[6]算法它是一种集成算法(类似于随机森林)主要用于挖掘异常(Anomaly)数据,或者说离群点挖掘,总之是在一大堆数据中,找出与其它数据的规律不太符合的数据。该算法不采样任何基于聚类或距离的方法,因此他和那些基于距离的的…

一文讲透Python机器学习特征工程中的特征标准化

在Python中&#xff0c;可通过scikit-learn模块中的StandardScaler()函数实现对特征的标准化处理。StandardScaler()函数处理的数据对象同样是每一列&#xff0c;也就是每一维特征。StandardScaler()函数通过去除平均值和缩放到单位方差来标准化特征&#xff0c;将样本特征值转…