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

从零认识命名管道:命名管道全解析

文章目录

  • 1. 引入
      • 问题:
      • 回答:
  • 2. 命名管道
    • 2.1 指令集方式创建管道文件
    • 2.2 系统调用方式创建命名管道
  • 3. 源码解析(面向过程)
    • Client
    • Server
  • 4. 结论分析(实验截图保留)
      • 1️⃣ 写端未打开前,读端 open 会阻塞
      • 2️⃣ 双方都成功 open 后通信开始
      • 3️⃣ 实现非亲缘进程通信
      • 4️⃣ 写端退出后,读端 read 返回 0 → 自动退出
  • 5. 源码(面向对象)
    • comm.hpp
    • server.cc
    • client.cc
  • 6. 总结


1. 引入

通过对匿名管道(pipe)的学习,我们已经能解决存在血缘关系的进程之间的通信问题。
但如果是 完全无关的两个进程,例如:

  • 进程 A
  • 进程 B

它们之间想要通信该怎么办呢?

于是就引出了 —— 命名管道(Named Pipe / FIFO) 的概念。


问题:

Q:两个无关进程 A、B 都打开同一个文件,操作系统是否会在内核中把该文件加载两次?

回答:

不会!因为没必要。

只要两个进程打开同一路径下的同一个文件,它们看到的就是同一份资源,自然就能实现进程间通信。

因为这个文件有路径、有名字,而且路径唯一
这个具有名字的管道文件,就是所谓的:

命名管道(FIFO)

它作为一个文件存在于文件系统中:
✔ 只会被打开,不会被刷新
✔ 不需要写入磁盘
✔ 操作系统保证其 FIFO 行为


2. 命名管道

2.1 指令集方式创建管道文件

使用 mkfifo 文件名 直接创建:

mkfifo fifo

文件类型显示为 p 说明它就是一个 FIFO:

在这里插入图片描述

echocat 实际就是两个独立进程,通过打开同一个 FIFO 文件实现通信:

在这里插入图片描述

删除命名管道文件:

在这里插入图片描述


2.2 系统调用方式创建命名管道

mkfifo() 系统调用用于在指定路径创建 FIFO 文件:

在这里插入图片描述


3. 源码解析(面向过程)

Client

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include "comm.hpp"
#include <unistd.h>
#include <fcntl.h>int main()
{// 打开管道文件int fd = open(FIFO_FILE, O_WRONLY);if (fd < 0){std::cerr << "open fifo error" << std::endl;return 2;}std::cout << "open fifo success" << std::endl;// 写文件std::string message;int cnt = 1;pid_t id = getpid();while (true){std::cout << "Please Enter#" << std::endl;std::getline(std::cin, message);message += (", message number:" + std::to_string(cnt) + ",[" + std::to_string(id) + "]");write(fd, message.c_str(), message.size()); // c_str方法 就是拿到string中的数据}// 关闭文件close(fd);return 0;
}

Server

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include "comm.hpp"
#include <unistd.h>
#include <fcntl.h>int main()
{umask(0);                        // 设置权限掩码int n = mkfifo(FIFO_FILE, 0666); // 创建管道文件,并设置权限if (n < 0){std::cout << "mkfile error" << std::endl;return 1;}std::cout << "mkfifo sucess" << std::endl;// 打开管道文件int fd = open(FIFO_FILE, O_RDONLY);if (fd < 0){std::cerr << "open fifo error" << std::endl;return 2;}std::cout << "open fifo success" << std::endl;// 读文件while (true){char buffer[1024];int number = read(fd, buffer, sizeof(buffer) - 1);if (number > 0){buffer[number] = 0;                               // 第number个位置充当\0std::cout << "Clent Say#" << buffer << std::endl; // 打印读到的内容}else if(number == 0){std::cout << "client quit!me too" << number << std::endl;break;}else{std::cerr << "read error" << std::endl;break;}}// 关闭文件close(fd);// 删除管道n = unlink(FIFO_FILE);if (n == 0){std::cout << "remove fifo success" << std::endl;}else{std::cout << "remove fifo failed" << std::endl;}return 0;
}

4. 结论分析(实验截图保留)


1️⃣ 写端未打开前,读端 open 会阻塞

在这里插入图片描述

读端会停在 open() 内部等待写端打开:

在这里插入图片描述


2️⃣ 双方都成功 open 后通信开始

在这里插入图片描述


3️⃣ 实现非亲缘进程通信

在这里插入图片描述


4️⃣ 写端退出后,读端 read 返回 0 → 自动退出

在这里插入图片描述


5. 源码(面向对象)

comm.hpp

#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include "comm.hpp"
#include <unistd.h>
#include <fcntl.h>#define FIFO_FILE "fifo"
#define PATH "."
#define FILENAME "fifo"
// 用宏来处理错误情况 \表示换行符
#define ERR_EXIT(m)         \do                      \{                       \perror(m);          \exit(EXIT_FAILURE); \} while (0)class NamedFifo
{
private:std::string _path;std::string _name;std::string _fifoname;public:NamedFifo(const std::string &path, const std::string &name): _path(path), _name(name){_fifoname = _path + "/" + _name;umask(0);                        // 设置权限掩码int n = mkfifo(FIFO_FILE, 0666); // 创建管道文件,并设置权限if (n < 0){ERR_EXIT("mkfile");}else{std::cout << "mkfifo sucess" << std::endl;}}~NamedFifo(){int n = unlink(_fifoname.c_str());if (n == 0){ERR_EXIT("unlink");}else{std::cout << "remove fifo failed" << std::endl;}return;}
};class FileOper
{
private:std::string _path;std::string _name;std::string _fifoname;int _fd;public:FileOper(const std::string &path, const std::string &name): _path(path), _name(name){_fifoname = _path + "/" + _name;}void OpenForRead(){_fd = open(_fifoname.c_str(), O_RDONLY);if (_fd < 0){ERR_EXIT("open");}else{std::cout << "open fifo success" << std::endl;}}void OpenForWrite(){_fd = open(_fifoname.c_str(), O_WRONLY);if (_fd < 0){ERR_EXIT("open");}else{std::cout << "open fifo success" << std::endl;}}void Write(){std::string message;int cnt = 1;pid_t id = getpid();while (true){std::cout << "Please Enter#" << std::endl;std::getline(std::cin, message);message += (", message number:" + std::to_string(cnt) + ",[" + std::to_string(id) + "]");write(_fd, message.c_str(), message.size()); // c_str方法 就是拿到string中的数据}}void Read(){while (true){char buffer[1024];int number = read(_fd, buffer, sizeof(buffer) - 1);if (number > 0){buffer[number] = 0;                               // 第number个位置充当\0std::cout << "Clent Say#" << buffer << std::endl; // 打印读到的内容}else if (number == 0){std::cout << "client quit!me too" << number << std::endl;break;}else{std::cerr << "read error" << std::endl;break;}}}void Close(){if (_fd > 0)close(_fd);}~FileOper(){}
};

server.cc

#include "comm.hpp"
int main()
{NamedFifo fifo("/", FILENAME);// 文件操作FileOper readerfile(PATH, FILENAME);readerfile.OpenForRead();readerfile.Read();readerfile.Close();return 0;
}

client.cc

#include "comm.hpp"
int main()
{FileOper writefiler(PATH, FILENAME);writefiler.OpenForWrite();writefiler.Write();writefiler.Close();return 0;
}

在这里插入图片描述


6. 总结

命名管道(FIFO)与匿名管道相比:

特性匿名管道命名管道
是否需要血缘关系✔ 需要❌ 不需要
是否有路径❌ 无✔ 有
是否可被非亲缘进程使用❌ 不行✔ 可以
是否持久化(可见于文件系统)❌ 不可见✔ 可见
生命周期进程结束即消失需要 unlink 删除

命名管道最大的优势:允许两个互不相关的进程通信。


http://www.dtcms.com/a/615635.html

相关文章:

  • 如何通过数字化手段提升优质中药饮片供应的效率?
  • 标准百度网站建设海口网站开发
  • 酒泉网站建设设计手机网站建设策划方案
  • 网站建设乙方义务三、网站开发使用软件环境
  • 展示网站建设的ppt用jquery做网站好吗
  • 企业建站费用情况企业主页的特点
  • 长沙专业建网站公司网站及数据库怎么做后门
  • 湖北省建设安全协会网站免费客户管理软件排行
  • 【LeetCode Hot 100】 136. 只出现一次的数字
  • 网站背景怎么设置云南企业网站开发
  • 企查查企业信息查询网站做网站属于程序员吗
  • 做网站电销话术虚拟主机和网站空间
  • 网站地图好处wordpress 无法显示
  • 当当网网站建设方案商务网站的类型一共有几大类
  • (119页PPT)智慧医院综合性智能化系统规划设计方案(附下载方式)
  • QT opencv通过轮廓坐标手工生成四边形案例详解
  • for dfs|二分
  • 第十六周Window的权限提升和维持
  • 怎么反编译易语言 | 深入了解反编译技术及其应用
  • 建设国外网站shanxi建设银行网站首页
  • 服务器搭建网站域名配置湖州营销网站建设
  • 深度学习Week1--数学基础 + 机器学习基础
  • 有没有做京东客好的网站推荐网站建设横幅系列素材
  • 站长工具短链接生成克拉玛依市住房和建设局网站
  • 解答网站内容优化策略佛山建站模板搭建
  • 屹晶微 EG2104 带SD功能半桥MOS管驱动芯片技术解析
  • 中国铁路保险网站房地产开发公司职位
  • 门户网站html.net 电子商务网站源码
  • 宁波网站建设选择荣胜网络免费海外网站建设
  • 设计公司网站模板做商城网站的项目背景图片