文章目录
- 七、进程间通信
- 1. 进程间通信分类
- 命名管道
- 未完待续
七、进程间通信
1. 进程间通信分类
命名管道
管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。命名管道是一种特殊类型的文件。
我们只需要使用 mkfifo 命令就可以在当前路径下创建命名管道。
Makefile:
.PHONY:all
all:pipe_server pipe_client
pipe_server:PipeServer.cc
g++ -o $@ $^ -std=c++11
pipe_client:PipeClient.cc
g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
rm -f pipe_server pipe_client
Comm.hpp:
#ifndef __COMM_HPP__
#define __COMM_HPP__
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <cerrno>
#include <cstring>
#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
{
cout << "mkfifo failed, error : " << errno << "errstring : " << strerror(errno) << endl;
}
}
~Fifo()
{
// 删除命名管道
int n = unlink(_path.c_str());
if (n == 0)
{
cout << "remove " << _path << " success" << endl;
}
else
{
cout << "remove failed, error : " << errno << "errstring : " << strerror(errno) << endl;
}
}
private:
// 文件路径 + 文件名
string _path;
};
#endif
pipe_server(服务端接收消息):
#include "Comm.hpp"
#include <unistd.h>
int main()
{
// 创建命名管道
Fifo fifo(Path);
// 打开命名管道文件
int rfd = open(Path, O_RDONLY);
if (rfd < 0)
{
cerr << "open failed, errno: " << errno << " , errnostring: " << strerror(errno) << endl;
return 1;
}
char buffer[1024];
// 循环读取管道数据
while (true)
{
ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);
if (n > 0)
{
buffer[n] = 0;
cout << "client says: " << buffer << endl;
}
else if (n == 0)
{
cout << "client quie, me too" << endl;
break;
}
else
{
cerr << "read failed, errno: " << errno << " , errnostring: " << strerror(errno) << endl;
break;
}
}
// 关闭命名管道文件
close(rfd);
return 0;
}
pipe_client(客户端输入消息):
#include "Comm.hpp"
int main()
{
// 以写的方式打开命名管道文件
int rfd = open(Path, O_WRONLY);
if (rfd < 0)
{
cerr << "open failed, errno: " << errno << " , errnostring: " << 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(rfd, inbuffer.c_str(), inbuffer.size());
if (n < 0)
{
cerr << "write failed, errno: " << errno << " , errnostring: " << strerror(errno) << endl;
}
}
// 关闭管道文件
close(rfd);
return 0;
}
结果: