前文:
Linux–进程间的通信-匿名管道
Linux–进程间的通信–进程池
命名管道的概念
命名管道是一种进程间通信(IPC)机制,运行不同进程之间进行可靠的、单向或双向的数据通信。
特点和作用:
跨平台性
:在WIndows和Linux系统中都有实现,因此具有良好的跨平台性。简单易用
: 使用命名管道进行通信相对简单。安全性
:命名管道充分利用了操作系统提供的安全特性,如WIndows的访问控制列表(ACL),从而确保通信的安全性。
命名管道的模拟实现
mkfifo是用于创建命名管道的命令,它的作用是在文件系统中创建一个特殊类型的文件,该文件可被多个进程用于进程间的通信。
这是mkfifo函数。
代码
Comm.hpp: 这里面包含了一个有关命名管道的类,包括管道的创建和销毁。
#ifndef __COMM_HPP__
#define __COMM_HPP__
#include<iostream>
#include<string>
#include<cstring>
#include<cerrno>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
using namespace std;
#define Mode 0666
#define Path "./fifo"
class fifo
{
public:
fifo(const string & path)
:_path(path)
{
umask(0);
int n=mkfifo(_path.c_str(),Mode);
if(n==0)
{
cout<< "mkfifo success" << endl;
}
else
{
cerr << "mkfifo failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
}
}
~fifo()
{
int n=unlink(_path.c_str());
if (n == 0)
{
cout << "remove fifo file " << _path << " success" << endl;
}
else
{
cerr << "remove failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
}
}
private:
string _path; //文件路径
};
#endif
PipeCilent.cc: 这是客户端(写端),将数据写入到命名管道文件;
#include"Comm.hpp"
int main()
{
int wfd=open(Path,O_WRONLY);
if(wfd<0)
{
cerr << "open failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
return 1;
}
string inbuffer;
while(true)
{
cout<<"Please Enter Your Message# ";
getline(cin,inbuffer);
if(inbuffer=="quit") break;
ssize_t n=write(wfd,inbuffer.c_str(),inbuffer.size());
if(n<0)
{
cerr << "write failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
break;
}
}
close(wfd);
return 0;
}
PipeServer.cc: 服务端(读端),需要对管道创建一个对象,读取管道中的内容。
#include "Comm.hpp"
#include<unistd.h>
int main()
{
fifo ff(Path);
int rfd=open(Path,O_RDONLY);
if(rfd<0)
{
cerr << "open failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
return 1;
}
//如果写端没有打开,那么open函数会受到阻塞,相当于命名管道与写端没有通信,
//open函数打开管道文件后如果没有连接写端就会等待
cout<<"open success"<<endl;
char buffer[1024];
while(true)
{
ssize_t n=read(rfd,buffer,sizeof(buffer)-1);
if(n>0)
{
buffer[n]=0;
cout << "client say : " << buffer << endl;
}
else if(n==0)
{
cout << "client quit, me too!!" << endl;
break;
}
else
{
cerr << "read failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
break;
}
}
close(rfd);
return 0;
}
解释
命名管道和匿名管道的区别:
匿名管道主要用于有血缘关系的进程间的通信,无法用于两个没有联系的进程;而命名管道可以在文件系统中通过路径名来进行使用;并且命名管道开辟的管道本质是一个文件,相对于匿名管道,管道空间比较大;创建方式不同:通过调用不同的系统调用来进行创建;所在位置不同:匿名管道会在内存中创建,而命名管道会在文件系统中创建;