当前位置: 首页 > news >正文

linux入门---命名管道

如何创建命名管道

使用mkfifo函数就可以在程序里面创建管道文件,该函数的声明如下:
在这里插入图片描述
该函数需要两个参数,第一个参数表示要在哪个路径下创建管道文件并且这个路径得待上管道文件的名字,因为每个文件都有对应的权限,所以函数的第二个参数就表示管道文件的权限,如果管道文件创建成功了该函数就返回0,如果创建失败该函数就直接返回对应的错误码:
在这里插入图片描述
那么接下来我们就创建一个管道文件出来瞧瞧,当前所在的路径如下:
在这里插入图片描述
那么我们就可以在程序里面通过函数mkfifo来创建管道文件:

#include<iostream>
#include<cerrno>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>    
using namespace std;
int main()
{umask(0);int n=mkfifo("/home/xbb/folder13/name_pipe",0600);if (n == 0){cout<<"creat success"<<endl;}else{cout << "errno: " << errno << " err string: " << strerror(errno) << endl;}return 0;
}

那么运行的结果就如下:
在这里插入图片描述
可以看到程序运行成功之后多出来了一个名为name_pipe的文件,并且这个文件是以p为开头,那么这个p就表示pipe的意思表示当前文件是管道文件,并且使用指令ls -il查看文件inode的时候也可以发现该文件有inode,那么这就说明管道文件是一个独立的文件,并且当前管道文件的大小为0表示当前文件里面没有任何的数据,然后使用下面的指令我们可以往屏幕上面不停地输出数据:cnt=0; while :; do echo "hello world-> $cnt"; let cnt++; sleep 1;done
在这里插入图片描述
那么这里我们就可以使用重定向,将原本输出到屏幕的数据输出到管道文件里面:
在这里插入图片描述
运行当前的指令就会不停地往管道里面输入数据,但是我们再创建一个进程不停地查看的管道文件的大小时,便会发现管道文件的大小没有发生任何变化:
在这里插入图片描述
可是虽然文件的大小没有发生任何的变化,但是当我们使用cat指令输出文件的内容时便又会发现,屏幕中打印了我们输入到文件里面的内容:
在这里插入图片描述
那么这就是管道文件的特性,那么接下来我们来看看命名管道的原理。

命名管道的原理

当我们在操作系统中打开一个文件,操作系统会创建一个struct file对象,该对象里面含有缓冲区和文件有广的操作方法,然后进程中的PCB中就会有一个指针指向一个名为file_struct的结构体,结构体中存在一个指针数组,数组的每个元素就指向不同文件的struct file对象:
在这里插入图片描述
但是这里存在一个问题,如果多个进程打开同一个文件,那操作系统会为这个文件创建多个struct file对象吗?答案是不会的,即使多个进程都打开了同一个文件,操作系统也只会创建一个struct file对象,所以这就会导致多个进程共用一个struct file,如果多个进程共用一个struct file的话,那这不就是让多个进程看到同一份资源嘛,所以这个strcut file就相当于是一个管道,只不过该管道文件的strcut file不会将内部缓冲区的数据刷新到磁盘中的文件里面,struct file对象中的数据都是内存级被写入和读取,那命名管道是如何做到让不同的进程看到同一份资源的呢?答案是让不同的进程打开指定名称(路径+文件名)的同一个文件,路径+文件名=唯一确定的文件,之所以叫命名管道是因为该管道是通过文件名的方式来看到同一份资源,而匿名管道是父子进程通过继承的方式来确定唯一性,并不通过文件名,所以将其称之为匿名管道。

命名管道的通信

函数mkfifo可以在程序里面创建命名管道,既然有创建那么同样的道理就有对应的函数来删除管道文件,unlink函数就可以用来删除创建的管道文件,该函数的声明如下:
在这里插入图片描述
函数内的参数表示要删除的管道文件,如果删除成功就返回0,删除失败就返回对应的错误码:
在这里插入图片描述
那么这里我们就可以使用这两个函数来实现进程之间的通信,首先创建一个文件,这个文件里面就包含两个函数,一个函数用来创建管道文件,一个函数用来删除管道文件:

#include<iostream>
#include<cerrno>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>    
using namespace std;
#define PIPE_PATH  "/home/xbb/folder13/name_pipe" 
bool createFifo(const string &path)
{}void removeFifo(string &path)
{}

根绝前面的经验我们可以很容易得实现createFifo函数,当mkfifo函数返回的值等于0的话就返回true,函数的返回值为非0的话就返回false:

bool createFifo(const string &path)
{umask(0);int n=mkfifo(path.c_str(),0600);if(n==0){return true;}else{cout << "errno: " << errno << " err string: " << strerror(errno) << endl;return false;}
}

同样的道理removeFifo函数里面就是调用unlink函数来进行删除,那么这里我们就用assert函数来进行判断文件是否删除成功,那这里的代码如下:

void removeFifo(const string &path)
{int n=unlink(path.c_str());	assert(n==0);(void)n;
}

那么这就是comm.hpp文件的内容,接下来我们还要创建server.cc文件和client.cc文件,server.cc文件负责从管道里面读取数据,client.cc文件就负责从管道里面写入数据,因为server.cc文件是读端,所以我们就让他来决定管道的创建和删除,那么在这个server.cc文件里面首先使用comm.hpp中的creatFifo函数创建管道,然后使用assert判断一下创建是否成功,创建成功之后就使用open函数以读的方式打开该管道文件,然后就得到这个函数的读端的下标

#include"comm.hpp"
int main()
{int r = createFifo(PIPE_PATH);assert(r);(void)r;int rfd=open(PIPE_PATH, O_RDONLY);cout<<"开始读取"<<endl;if(rfd<0){exit(1);}return 0;
}

走到这里我们的管道文件就在当前进程顺利的创建并且打开了,那么这时我们就可以创建一个while循环不停地往管道里面读取信息,因为读取的信息要放到一个地方进行存储,所以在循环之前我们还得穿件一个数组用来充当缓冲区,那么在循环里面就可以使用read函数从下标为rfd的文件里面读取数据,将读取的数据放到缓冲区里面,因为读取数据的时候可能会出现结束或者出错的情况,所以这里还得创建一个变量用来记录read函数的返回值,那么这里的代码如下:

#include"comm.hpp"
int main()
{int r = createFifo(PIPE_PATH);assert(r);(void)r;int rfd=open(PIPE_PATH, O_RDONLY);cout<<"开始读取"<<endl;if(rfd<0){exit(1);}char buffer[1024]={0};while(true){ssize_t s = read(rfd, buffer, sizeof(buffer)-1);}return 0;
}

然后就使用if else语句对size的值进行判断,如果size的值大于0就表示当前的读取是正确的,我们直接输出buffer里面的值,如果size的值等于0就表示当前的读取结束了直接使用break结束while循环,如果sizede值小于0就表示当前的读取出现了错误,那么我们就打印一下错误码看看哪里出现了问题并使用break结束循环,循环结束之后我们就关闭当前打开的管道文件,并且使用removeFifo函数删除管道文件,那么这里的代码如下:

#include"comm.hpp"
int main()
{int r = createFifo(PATH);assert(r);(void)r;int rfd=open(PATH, O_RDONLY);cout<<"开始读取"<<endl;if(rfd<0){exif(1);}char buffer[1024]={0};while(true){ssize_t s = read(rfd, buffer, sizeof(buffer)-1);if(s > 0){buffer[s] = 0;std::cout << "client->server# " << buffer << std::endl;}else if(s == 0){std::cout << "client quit, me too!" << std::endl;break;}else{std::cout << "err string: " << strerror(errno) << std::endl;break;}}close(rfd);// sleep(10);removeFifo(NAMED_PIPE);return 0;
}

那么这是server.cc文件的内容,那么对于client.cc文件也是同样的道理,首先以写的方式打开管道文件然后进行判断,再创建一个缓冲区将想要写入管道的信息先写入到缓冲区里,再使用write函数将缓冲区的内容放到写入到管道里面,然后根据write函数的返回值来判断当前的写入是否成功,因为要多次写入所以这里也得添加while循环来进行循环写入:

#include"comm.hpp"
int main()
{int Wfd=open(PIPE_PATH, O_WRONLY);if(Wfd < 0) exit(1);char buffer[1024];cout<<"client say"<<endl;while(true){fgets(buffer, sizeof(buffer), stdin);if(strlen(buffer) > 0) {//将末尾的/n去掉buffer[strlen(buffer)-1] = 0;}ssize_t n = write(Wfd, buffer, strlen(buffer));assert(n == strlen(buffer));(void)n;}close(Wfd);return 0;
}

此文件写完之后我们就可以来完成makefile文件,首先该功能的运行需要让两个文件都生成可执行程序,所以这里就将指令较为all,该指令需要client和server生成可执行程序:

.PHONY:
all: client server

但是当前路径下并没有可执行程序,所以我们还得添加两个可执行程序对应的实现方法和依赖文件:

.PHONY:
all: client serverclient:client.ccg++ -o $@ $^ -std=c++11 -g
server:server.ccg++ -o $@ $^ -std=c++11 -g

然后就是删除指令,该指令将生成的两个可执行程序删除就行,那么makefile的全部内容如下:

.PHONY:
all: client serverclient:client.ccg++ -o $@ $^ -std=c++11 -g
server:server.ccg++ -o $@ $^ -std=c++11 -g.PHONY:
clean:rm -f client server

那么接下来我们就可以进行测试,首先使用make指令生成两个可执行程序:
在这里插入图片描述
然后先打开server再打开client程序,然后就可以看到这样的现象:
在这里插入图片描述
因为写端没有打开,所以server一直阻塞在open函数那里,当我们运行client程序之后就可以看到server进程打印出来了内容:
在这里插入图片描述
在这里插入图片描述
然后我们往client进程里面输入内容,然后便可以看到,输入导client里面的内容输出到server这里:
在这里插入图片描述
在这里插入图片描述
那么这就是命名管道的通信。

相关文章:

linux入门---命名管道

如何创建命名管道 使用mkfifo函数就可以在程序里面创建管道文件&#xff0c;该函数的声明如下&#xff1a; 该函数需要两个参数&#xff0c;第一个参数表示要在哪个路径下创建管道文件并且这个路径得待上管道文件的名字&#xff0c;因为每个文件都有对应的权限&#xff0c;所…...

SpringBoot2.0入门(详细文档)

文章目录 Springboot是什么Springboot2.x依赖环境和版本新特性说明为什么学习Springboot从springboot优点来看从未来发展的趋势来看 开发环境Spring Boot开发环境搭建和项目启动jdk 的配置Spring Boot 工程的构建maven配置IDEA 快速构建maven 创建工程常用注解 完整代码 Spring…...

Aztec的隐私抽象:在尊重EVM合约开发习惯的情况下实现智能合约隐私

1. 引言 Aztec的架构&#xff0c;不同于当前“通过EVM兼容执行环境”所实现的区块链水平扩容趋势。Aztec内部笑称其构建的为首个非zkEVM协议。 Aztec专注于实现&#xff1a; 成为理解和需要智能合约隐私的开发者的终极解决方案。 Aztec为开发者提供构建隐私优先app所需的网…...

【Vue】详细介绍Vue项目的目录结构及各个核心文件的示例代码

Vue.js并没有严格的文件和目录结构要求&#xff0c;但一般情况下&#xff0c;我们的Vue项目目录结构如下&#xff1a; ├── node_modules/ # 项目依赖的 node 模块 ├── public/ # 公共资源目录 │ ├── favicon.ico # 网页图标 │ └──…...

【人大金仓】迁移MySql数据库到人大金仓,出现sys_config表重复

需要迁移的数据库中有张表名称为sys_config&#xff0c;查询的时候查询结果不符合我们的预期&#xff0c;经咨询金仓售后人员后得知和系统表重名… 解决问题方法如下&#xff1a; alter database [数据库名] set search_path to "$user", [模式名,&#xff08;可选&…...

linux内核进程间通信IPC----消息队列

消息队列&#xff1a;提供一种从一个进程向另一个进程发送一个数据块的方法。与FIFO相比&#xff0c;消息队列的优势在于&#xff0c;它独立于发送和接收进程而存在。 1.链表式结构组织&#xff0c;存放于内核。 2.通过队列标识来引用。 3.通过一个数据类型来索引指定的数据。 …...

PHP实现微信小程序状态检测(违规、暂停服务、维护中、正在修复)

实现原理 进入那些状态不正常的小程序会被重定向至一个Url&#xff0c;使用抓包软件抓取这个Url&#xff0c;剔除不必要参数&#xff0c;使用cURl函数请求网页获得HTML内容&#xff0c;根据内容解析出当前APPID的小程序的状态。 代码 <?php// 编码header(Content-type:ap…...

ubuntu在线直接升级

前几天VMware上安装了ubuntu&#xff0c;当时的内核版本支持(ipguard,加密软件)&#xff0c;后来ubuntu自动升级了linux内核&#xff0c;导致加入软件不支持&#xff0c;无法访问加密文件了。后来加密软件商更新了软件&#xff0c;但还是赶不上linux内核更新速度&#xff0c;还…...

学习笔记:卸载nav2 navigation2导航

nav2二进制文件安装 nav2导航安装方式分为二进制文件安装和源码方式安装&#xff0c;如果想用最快的方式跑通代码&#xff0c;推荐二进制安装&#xff0c;不用编译&#xff0c;没有缺少依赖编译失败的烦恼&#xff0c; 安装命令&#xff1a; sudo apt install ros-$ROS_DISTR…...

觉非科技数据闭环系列 | BEV感知研发实践

随着自动驾驶迈向量产场景&#xff0c;“BEV感知数据闭环”已成为新一代自动驾驶量产系统的核心架构。数据成为了至关重要的技术驱动力&#xff0c;发挥数据闭环的飞轮效应或将成为下半场从1到N的胜负关键。 觉非科技在此方面已进行了大量的研究工作&#xff0c;并在实际量产项…...

程序员情绪把控

文章目录 建议情绪 建议 保持稳定的情绪在工作中非常重要&#xff0c;以下是一些建议&#xff1a; 自我意识&#xff1a;保持对自己情绪的觉察和理解&#xff0c;了解自己的情绪状态和触发情绪的因素。通过自我反省和观察&#xff0c;你可以更好地管理和调节情绪。 健康生活方…...

弱监督目标检测:ALWOD: Active Learning for Weakly-Supervised Object Detection

论文作者&#xff1a;Yuting Wang,Velibor Ilic,Jiatong Li,Branislav Kisacanin,Vladimir Pavlovic 作者单位&#xff1a;Rutgers University;The Institute for Artificial Intelligence Research and Development of Serbia;Nvidia Corporation 论文链接&#xff1a;http:…...

驱动开发 day3

总结&#xff1a;自动创建设备节点udev的流程 1.如何创建节点 手动创建&#xff1a;mknod 地址 设备文件类型 主设备号 次设备号(0 - 255) 自动创建&#xff1a;devfs (创建节点的逻辑在内核 ---> 2.4版本以前使用) udev (创建节点的逻辑在应用层) mdev (轻量级的udev) 2.…...

许可license分析 第一章

许可分析是指对软件许可证进行详细的分析和评估&#xff0c;以了解组织内部对软件许可的需求和使用情况。通过许可分析&#xff0c;可以帮助组织更好地管理和优化软件许可证的使用。以下是一些可能的许可分析方法和步骤&#xff1a; 收集许可证信息&#xff1a;首先&#xff0c…...

Goby 漏洞发布|管家婆订货易在线商城 SelectImage.aspx 文件上传漏洞

漏洞名称&#xff1a;管家婆订货易在线商城 SelectImage.aspx 文件上传漏洞 English Name&#xff1a; GJP SelectImage.aspx file upload vulnerability CVSS core: 9.8 影响资产数&#xff1a;2617 漏洞描述&#xff1a; 任我行率先针对中小企业推出了管家婆进销存、财务…...

Android屏幕录制

这里使用Java语言编写实现&#xff0c;完整代码如下&#xff1a; 文件 AndroidMainfest.xml 的主要配置 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"package"…...

实在智能牵手埃林哲,“TARS-RPA-Agent+云时通”双剑合璧共推企业数字化转型

近日&#xff0c;《数字中国建设整体布局规划》进一步明确了数字化发展的方向和节奏&#xff0c;对企业数字化建设提出了新要求。回看过去几十年&#xff0c;信息化建设如火如荼&#xff0c;各类IT系统如雨后春笋般涌现&#xff0c;系统的自动化操作及系统间数据交互共享等需求…...

拥有这个中文版CustomGPT,你也能定制自己的AI问答机器人

人工智能技术的快速发展为各行各业带来了前所未有的机会&#xff0c;其中之一就是定制化的问答机器人。这些机器人可以用于客户支持、知识管理、虚拟助手等多个领域&#xff0c;帮助企业提高效率&#xff0c;提供更好的用户体验。很多人可能都知道通过CustomGPT能够设计自己的人…...

fastadmin 基本使用配置

fastadmin 版本 1.3.5 thinkphp 版本 5.0.25 配置 cache 为 redis 保存 // ---------------------------------------------------------------------- // | 缓存设置 // ---------------------------------------------------------------------- cache …...

netty 线程组

我们的bossgroup和workgroup都是使用的NioEventLoopGroup。其内部有一个EventExecutor类型的数组用来存储所有的线程组。 NioEventLoopGroup {EventExecutor[] children; }NioEventLoopGroup继承自MultithreadEventExecutorGroup&#xff0c;构造函数不指定线程数默认会根据系…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...