> 文章列表 > 【Linux】进程间通信 -- 命名管道

【Linux】进程间通信 -- 命名管道

【Linux】进程间通信 -- 命名管道

前言

管道的通信中,除了匿名管道,还有一个命名管道
匿名管道只支持具有“亲戚关系”的进程间通信,而命名管道就可以支持不同的,任意的进程通信。
那就下来就开始我们今天的学习。

在这里插入图片描述

文章目录

  • 前言
  • 一. 命名管道
  • 二. 命名管道的应用
  • 结束语

一. 命名管道

匿名管道的两种使用方式:指令的 ' | ' 和pipe()函数
命名管道也有两种使用方式:指令的 ' mkfifo 和 mkfile()函数'

我们使用一下指令的mkfile
mkfilo 命名管道名
【Linux】进程间通信 -- 命名管道
管道文件属性的最前面的是p,普通文件是 -,链接文件是l

我们简单使用一下命名管道
【Linux】进程间通信 -- 命名管道
这两个是不同的进程,一个是echo "hello" 将" hello "输出到显示器,但是重定向到 fifo管道中
一个是将fifo管道内容读出,重定向到cat,cat内部再将内容重定向到显示器
这样就实现两个不同进程通信了。

我们还可以更直观的感受,两个不同进程的通信。
在输入处,改成循环,这样写数据的进程就可以一直输入读数据的进程就一直读取。
【Linux】进程间通信 -- 命名管道

命名管道,也是内存级文件,并不会像普通文件那样刷盘,将数据写入磁盘,同匿名管道一般,其内部就是一个缓冲区

二. 命名管道的应用

上面我们使用了指令层面的命名管道,接下来我们要使用代码创建命名管道,并且基于命名管道,实现多进程通信。

创建管道文件的函数
【Linux】进程间通信 -- 命名管道

第一个参数是要创建的管道文件的文件名,第二个参数是管道文件的默认权限
创建成功返回0不成功返回-1

我们创建一个客户端,一个服务端,客户端写数据,服务端读数据。
因为我们要实现不同进程的通信,所以需要两个可执行程序。我们还可以将一些公共的信息放在一个 .hpp文件中

comm.hpp

#include<iostream>
#include<string>//管道名
const std::string filename="./fifo";
//默认权限
const mode_t mode=0666;

我们让server客户端创建管道
server.cpp

#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<cstring>
#include<cerrno>
#include<fcntl.h>
#include<unistd.h>
#include"comm.hpp"//服务端
//接收数据
int main()
{//1. 创建管道文件,只需要创建一次//更改掩码umask(0);//该掩码的改变只印象该进程int n=mkfifo(filename.c_str(),mode);if(n!=0){std::cout<<errno<<" : "<<strerror(errno)<<std::endl;return 1;}std::cout<<"create file success"<<std::endl;//2.服务端以读方式打开管道文件int rfd=open(filename.c_str(),O_RDONLY);if(rfd<0){std::cout<<errno<<" : "<<strerror(errno)<<std::endl;return 2;}std::cout<<"open file success , begin ipc"<<std::endl;//3. 正常通信while(true){char buffer[64]={0};ssize_t n=read(rfd,buffer,sizeof(buffer)-1);if(n>0){buffer[n]='\\0';std::cout<<"client# "<<buffer<<std::endl;}else if(n==0){//写端关闭,返回值会变成0std::cout<<"通信结束"<<std::endl;break;}else{std::cout<<errno<<" : "<<strerror(errno)<<std::endl;}}close(rfd);//删除管道文件unlink(filename.c_str());return 0;
}

client.cpp

#include<iostream>
#include"comm.hpp"
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<cstring>
#include<cassert>int main()
{//1.不需要创建管道,直接以写的方式打开就好int wfd=open(filename.c_str(),O_WRONLY);if(wfd<0){std::cerr<<errno<<" : "<<strerror(errno)<<std::endl;return 1;}//开始进行常规通信char buffer[64];while(true){std::cout<<"请输入你的消息:";//C语言的函数,关于字符串的输出输入不需要-1//系统调用的函数,关于字符串的函数需要-1char*msg=fgets(buffer,sizeof(buffer)-1,stdin);assert(msg);(void)msg;//将\\n覆盖掉//abcdef\\n\\0   //01234567buffer[strlen(buffer)-1]='\\0';//识别退出信息//忽略大小写的比较if(strcasecmp(buffer,"quit")==0){//输入"quit",就跳出循环break;}ssize_t n=write(wfd,buffer,strlen(buffer));assert(n>=0);(void)n;}close(wfd);return 0;
}

部分运行结果如下
【Linux】进程间通信 -- 命名管道

结束语

本篇文章内容到此结束,感谢你的阅读

如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述