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,构造函数不指定线程数默认会根据系…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
