命名管道:简单案例实现

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

🌴专栏链接: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.hqwc.cn/news/231806.html

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

相关文章

目标检测——R-CNN算法解读

论文&#xff1a;Rich feature hierarchies for accurate object detection and semantic segmentation 作者&#xff1a;Ross Girshick, Jeff Donahue, Trevor Darrell, Jitendra Malik 链接&#xff1a;https://arxiv.org/abs/1311.2524 代码&#xff1a;http://www.cs.berke…

拼图 游戏

运行出的游戏界面如下&#xff1a;按住A不松开&#xff0c;显示完整图片&#xff1b;松开A显示随机打乱的图片 User类 package domain;/*** ClassName: User* Author: Kox* Data: 2023/2/2* Sketch:*/ public class User {private String username;private String password;p…

easyrecovery如何恢复手机数据及硬盘数据恢复方法

EasyRecovery16是一款优秀的数据恢复软件&#xff0c;不仅能够兼容windows和mac双重系统&#xff0c;同时还能够识别u盘、存储卡、手机等多种数据储存设备&#xff0c;可恢复的文件类型更是多达百余种。还贴心地准备个人版、专业版和企业版的下载&#xff0c;增加了用户的可选性…

WordPress 外链跳转插件

WordPress 外链跳转插件是本站开发的一款WordPress插件&#xff0c;能对文中外链添加一层过滤&#xff0c;有效防止追踪&#xff0c;以及提醒用户。 类似于知乎、CSDN打开其他链接的提示。 后台可以设置白名单 学习资料源代码&#xff1a;百度网盘 密码&#xff1a;123

什么是主机安全,有什么作用?

当今数字化时代&#xff0c;网络安全威胁和风险日益突出&#xff0c;已成为企业面临的重大安全挑战。网络攻击者不断尝试利用各种技术和手段对企业网络资源进行探测和攻击&#xff0c;如&#xff1a;利用漏洞、木马、钓鱼、勒索等方式窃取数据、破坏系统、篡改信息。因此&#…

mybatis关于namespace以及id以及Mapper接口命名的说明(了解)

1、建库建表 CREATE DATABASE mybatis-example;USE mybatis-example;CREATE TABLE t_emp(emp_id INT AUTO_INCREMENT,emp_name CHAR(100),emp_salary DOUBLE(10,5),PRIMARY KEY(emp_id) );INSERT INTO t_emp(emp_name,emp_salary) VALUES("tom",200.33); INSERT INTO…

第十五届蓝桥杯(Web 应用开发)模拟赛 2 期-大学组(详细分析解答)

目录 1.相不相等 1.1 题目要求 1.2 题目分析 1.3 源代码 2.三行情书 2.1 题目要求 2.2 题目分析 2.3 源代码 3.电影院在线订票 3.1 题目要求 3.2 题目分析 3.3 源代码 4.老虎坤&#xff08;不然违规发不出来&#xff09; 4.1 题目要求 4.2 题目分析 4.3 源代码 …

操作系统面试题

操作系统 操作系统是管理计算机硬件和软件资源的程序&#xff0c;是系统软件 操作系统功能 进程和线程管理存储管理文件管理设备管理网络管理安全管理 用户态和内核态 用户态运行的进程可以直接读取用户程序的数据&#xff0c;权限较低内核态运行的进程几乎可以访问计算机…

zookeeper实操课程Acl 访问权限控制,命令行测试

本系列是zookeeper相关的实操课程&#xff0c;课程测试环环相扣&#xff0c;请按照顺序阅读测试来学习zookeeper。阅读本文之前&#xff0c;请先阅读----​​​​​​zookeeper 单机伪集群搭建简单记录&#xff08;实操课程系列&#xff09;。 阅读本文之前&#xff0c;请先阅读…

【linux防火墙】iptables的四表五链以及实操应用

目录 一、防火墙的基本认识 浅提一下iptables 二、防火墙的分类 三、netfilter中的五个勾子函数和报文流向 四、netfilter/iptables的简介 五、iptables的原理讲解和四表五链 内核中数据包传输的过程&#xff1a; 六、iptables iptables的语法&#xff1a; 七、实操 七…

西工大网络空间安全学院计算机系统基础实验一(9, 10, 11, 12, 13)

还是那句话&#xff0c;专心做好你自己的&#xff0c;老老实实把基础打好&#xff0c;不要被其他人带跑节奏&#xff0c;不要跟他打&#xff0c;跟着这系列博客&#xff0c;稳扎稳打一步一步来。即使你VMware workstation没下载好&#xff0c;即使你Ubuntu虚拟机没配好&#xf…

lxd提权

lxd/lxc提权 漏洞介绍 lxd是一个root进程&#xff0c;它可以负责执行任意用户的lxd&#xff0c;unix套接字写入访问操作。而且在一些情况下&#xff0c;lxd不会调用它的用户权限进行检查和匹配 原理可以理解为用用户创建一个容器&#xff0c;再用容器挂载宿主机磁盘&#xf…