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函数就可以在程序里面创建管道文件,该函数的声明如下: 该函数需要两个参数,第一个参数表示要在哪个路径下创建管道文件并且这个路径得待上管道文件的名字,因为每个文件都有对应的权限,所…...

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

Aztec的隐私抽象:在尊重EVM合约开发习惯的情况下实现智能合约隐私
1. 引言 Aztec的架构,不同于当前“通过EVM兼容执行环境”所实现的区块链水平扩容趋势。Aztec内部笑称其构建的为首个非zkEVM协议。 Aztec专注于实现: 成为理解和需要智能合约隐私的开发者的终极解决方案。 Aztec为开发者提供构建隐私优先app所需的网…...
【Vue】详细介绍Vue项目的目录结构及各个核心文件的示例代码
Vue.js并没有严格的文件和目录结构要求,但一般情况下,我们的Vue项目目录结构如下: ├── node_modules/ # 项目依赖的 node 模块 ├── public/ # 公共资源目录 │ ├── favicon.ico # 网页图标 │ └──…...
【人大金仓】迁移MySql数据库到人大金仓,出现sys_config表重复
需要迁移的数据库中有张表名称为sys_config,查询的时候查询结果不符合我们的预期,经咨询金仓售后人员后得知和系统表重名… 解决问题方法如下: alter database [数据库名] set search_path to "$user", [模式名,(可选&…...

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

PHP实现微信小程序状态检测(违规、暂停服务、维护中、正在修复)
实现原理 进入那些状态不正常的小程序会被重定向至一个Url,使用抓包软件抓取这个Url,剔除不必要参数,使用cURl函数请求网页获得HTML内容,根据内容解析出当前APPID的小程序的状态。 代码 <?php// 编码header(Content-type:ap…...
ubuntu在线直接升级
前几天VMware上安装了ubuntu,当时的内核版本支持(ipguard,加密软件),后来ubuntu自动升级了linux内核,导致加入软件不支持,无法访问加密文件了。后来加密软件商更新了软件,但还是赶不上linux内核更新速度,还…...
学习笔记:卸载nav2 navigation2导航
nav2二进制文件安装 nav2导航安装方式分为二进制文件安装和源码方式安装,如果想用最快的方式跑通代码,推荐二进制安装,不用编译,没有缺少依赖编译失败的烦恼, 安装命令: sudo apt install ros-$ROS_DISTR…...

觉非科技数据闭环系列 | BEV感知研发实践
随着自动驾驶迈向量产场景,“BEV感知数据闭环”已成为新一代自动驾驶量产系统的核心架构。数据成为了至关重要的技术驱动力,发挥数据闭环的飞轮效应或将成为下半场从1到N的胜负关键。 觉非科技在此方面已进行了大量的研究工作,并在实际量产项…...
程序员情绪把控
文章目录 建议情绪 建议 保持稳定的情绪在工作中非常重要,以下是一些建议: 自我意识:保持对自己情绪的觉察和理解,了解自己的情绪状态和触发情绪的因素。通过自我反省和观察,你可以更好地管理和调节情绪。 健康生活方…...

弱监督目标检测:ALWOD: Active Learning for Weakly-Supervised Object Detection
论文作者:Yuting Wang,Velibor Ilic,Jiatong Li,Branislav Kisacanin,Vladimir Pavlovic 作者单位:Rutgers University;The Institute for Artificial Intelligence Research and Development of Serbia;Nvidia Corporation 论文链接:http:…...

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

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

Goby 漏洞发布|管家婆订货易在线商城 SelectImage.aspx 文件上传漏洞
漏洞名称:管家婆订货易在线商城 SelectImage.aspx 文件上传漏洞 English Name: GJP SelectImage.aspx file upload vulnerability CVSS core: 9.8 影响资产数:2617 漏洞描述: 任我行率先针对中小企业推出了管家婆进销存、财务…...
Android屏幕录制
这里使用Java语言编写实现,完整代码如下: 文件 AndroidMainfest.xml 的主要配置 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"package"…...

实在智能牵手埃林哲,“TARS-RPA-Agent+云时通”双剑合璧共推企业数字化转型
近日,《数字中国建设整体布局规划》进一步明确了数字化发展的方向和节奏,对企业数字化建设提出了新要求。回看过去几十年,信息化建设如火如荼,各类IT系统如雨后春笋般涌现,系统的自动化操作及系统间数据交互共享等需求…...

拥有这个中文版CustomGPT,你也能定制自己的AI问答机器人
人工智能技术的快速发展为各行各业带来了前所未有的机会,其中之一就是定制化的问答机器人。这些机器人可以用于客户支持、知识管理、虚拟助手等多个领域,帮助企业提高效率,提供更好的用户体验。很多人可能都知道通过CustomGPT能够设计自己的人…...
fastadmin 基本使用配置
fastadmin 版本 1.3.5 thinkphp 版本 5.0.25 配置 cache 为 redis 保存 // ---------------------------------------------------------------------- // | 缓存设置 // ---------------------------------------------------------------------- cache …...

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

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...